• HDU 5409 CRB and Graph 双连通缩点 + st表


    HDU 5409

    显然要先双连通缩成一棵树。 然后对于树上的边才有答案。

    对于一条边来说, 两侧的最大值分为mx1 , mx2 , 那么 u 一定是min(mx1, mx2), v 一定是 u + 1。

    这个经过仔细分析一下就能得到, 然后按dfs序建个st表就好啦。

    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 1e5 + 2;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}
    
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    int n, m;
    vector<PII> G[N];
    vector<PII> bG[N];
    
    int stk[N], top;
    int dfn[N], low[N], belong[N], idx, cnt;
    int mx[N];
    bool brige[N];
    PII ans[N];
    int in[N], ot[N];
    
    int Log[N];
    struct ST {
        int dp[N][20]; int ty;
        void build(int n, int b[], int _ty) {
            ty = _ty;
            for(int i = -(Log[0]=-1); i < N; i++)
            Log[i] = Log[i - 1] + ((i & (i - 1)) == 0);
            for(int i = 1; i <= n; i++) {
                dp[in[i]][0] = mx[i];
            }
            for(int j = 1; j <= Log[n]; j++)
                for(int i = 1; i+(1<<j)-1 <= n; i++)
                    dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
        }
        inline int query(int x, int y) {
            if(x > y) return 0;
            int k = Log[y - x + 1];
            return ty * max(dp[x][k], dp[y-(1<<k)+1][k]);
        }
    } rmq;
    
    void tarjan(int u, int pid) {
        dfn[u] = low[u] = ++idx;
        stk[++top] = u;
        for(auto &e : G[u]) {
            if(e.fi == pid) continue;
            if(!dfn[e.se]) {
                tarjan(e.se, e.fi);
                chkmin(low[u], low[e.se]);
                if(dfn[u] < low[e.se]) {
                    brige[e.fi] = true;
                }
            } else {
                chkmin(low[u], dfn[e.se]);
            }
        }
        if(dfn[u] == low[u]) {
            cnt++;
            while(1) {
                int v = stk[top--];
                belong[v] = cnt;
                chkmax(mx[cnt], v);
                if(v == u) break;
            }
        }
    }
    
    void go(int u, int fa) {
        in[u] = ++idx;
        for(auto &e : bG[u]) {
            if(e.se == fa) continue;
            go(e.se, u);
        }
        ot[u] = idx;
    }
    
    void solve(int u, int fa) {
        for(auto &e : bG[u]) {
            int v = e.se, eid = e.fi;
            if(v == fa) continue;
            int mx1 = rmq.query(in[v], ot[v]);
            int mx2 = max(rmq.query(1, in[v] - 1), rmq.query(ot[v] + 1, cnt));
            ans[eid].fi = min(mx1, mx2);
            ans[eid].se = ans[eid].fi + 1;
            solve(v, u);
        }
    }
    
    int main() {
    
        int T; scanf("%d", &T);
        while(T--) {
            scanf("%d%d", &n, &m);
            idx = cnt = top = 0;
            for(int i = 1; i <= n; i++) {
                G[i].clear();
                bG[i].clear();
                dfn[i] = low[i] = 0;
                mx[i] = 0;
            }
            for(int i = 1; i <= m; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                G[u].push_back(mk(i, v));
                G[v].push_back(mk(i, u));
                brige[i] = false;
                ans[i] = mk(0, 0);
            }
    
            for(int i = 1; i <= n; i++) {
                if(!dfn[i]) {
                    tarjan(i, 0);
                }
            }
            for(int u = 1; u <= n; u++) {
                for(auto &e : G[u]) {
                    if(belong[u] == belong[e.se]) continue;
                    bG[belong[u]].push_back(mk(e.fi, belong[e.se]));
                }
            }
    
            idx = 0;
            go(1, 0);
    
            rmq.build(cnt, mx, 1);
    
            solve(1, 0);
    
            for(int i = 1; i <= m; i++) {
                printf("%d %d
    ", ans[i].fi, ans[i].se);
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    【用程序思维学习英语】
    【python3】修饰器简单理解
    【FLASK】发送QQ邮件
    【FLASK】数据库迁移
    【python3】with的用法
    【flask】工厂函数和蓝本的作用
    使用Python中的xltpl模块填充excel表格模板文件
    Python添加excel表格的批注
    在原有表格基础上面进行添加内容修改格式等操作
    Python操作excel表格库的介绍
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11159335.html
Copyright © 2020-2023  润新知