• HDU3686 Traffic Real Time Query


    按照vdcc缩点之后一条边只会属于一个新的点集,由于这棵树上满足(不是割点) - (割点) - (不是割点)的连接方法,所以求两条边之间的必经点就是(树上距离 / 2),倍增跳lca即可
    考虑到缩点后树上点数的编号可能超过n,所以与树有关的数组开两倍N
    又是一个模板

    Code:

    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    
    const int N = 1e4 + 5;
    const int M = 1e5 + 5;
    const int Lg = 25;
    
    int n, m, qn, tot, head[2][N << 1], top, sta[N];
    int dfsc, dfn[N], low[N], dccCnt, root;
    int bel[N], eb[M], fa[N << 1][Lg], dep[N << 1], id[N];
    bool cut[N], vis[N << 1];
    vector <int> dcc[N];
    
    struct Edge {
        int to, nxt, id;
    } e[M << 2];
    
    inline void add(int type, int from, int to, int eid) {
        e[++tot].to = to;
        e[tot].id = eid;
        e[tot].nxt = head[type][from];
        head[type][from] = tot;
    }
    
    inline void read(int &X) {
        X = 0;
        char ch = 0;
        int op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline int min(int x, int y) {
        return x > y ? y : x;
    }
    
    void tarjan(int x) {
        dfn[x] = low[x] = ++dfsc;
        sta[++top] = x;
        if(x == root && head[0][x] == 0) {
            dcc[++dccCnt].push_back(x);
            return;
        }
        
        int son = 0;
        for(int i = head[0][x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(!dfn[y]) {
                tarjan(y);
                low[x] = min(low[x], low[y]);
                if(dfn[x] <= low[y]) {
                    ++son;
                    if(x != root || son > 1) cut[x] = 1;
                    ++dccCnt;
                    for(int z; ; ) {
                        z = sta[top--];
                        dcc[dccCnt].push_back(z);
                        if(z == y) break;
                    }
                    dcc[dccCnt].push_back(x);
                }
            } else low[x] = min(low[x], dfn[y]);
        }
    }
    
    void dfs(int x, int fat, int depth) {
        vis[x] = 1, fa[x][0] = fat, dep[x] = depth;
        for(int i = 1; i <= 15; i++)
            fa[x][i] = fa[fa[x][i - 1]][i - 1];
        for(int i = head[1][x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(vis[y]) continue;
            dfs(y, x, depth + 1);
        }
    }
    
    inline void swap(int &x, int &y) {
        int t = x;
        x = y;
        y = t;
    }
    
    inline int getLca(int x, int y) {
        if(dep[x] < dep[y]) swap(x, y);
        for(int i = 15; i >= 0; i--)
            if(dep[fa[x][i]] >= dep[y])
                x = fa[x][i];
        if(x == y) return x;
        for(int i = 15; i >= 0; i--)
            if(fa[x][i] != fa[y][i])
                x = fa[x][i], y = fa[y][i];
        return fa[x][0];
    }
    
    int main() {
        for(; ; ) {
            read(n), read(m);
            if(n == 0 && m == 0) break;
            tot = 0;
            memset(head, 0, sizeof(head));
            for(int x, y, i = 1; i <= m; i++) {
                read(x), read(y);
                add(0, x, y, i), add(0, y, x, i);
            } 
            
            dfsc = dccCnt = top = 0;
            memset(dfn, 0, sizeof(dfn));
            memset(low, 0, sizeof(low));
            memset(cut, 0, sizeof(cut));
            for(int i = 1; i <= n; i++) dcc[i].clear();
            
            for(int i = 1; i <= n; i++)
                if(!dfn[i]) tarjan(root = i);
            
            int now = dccCnt;
            for(int i = 1; i <= n; i++)
                if(cut[i]) id[i] = ++now;
            
    /*        printf("
    ");
            for(int i = 1; i <= dccCnt; i++, printf("
    ")) {
                for(unsigned int j = 0; j < dcc[i].size(); j++)
                    printf("%d ", dcc[i][j]);
            }
            printf("
    ");   */
                
            for(int i = 1; i <= dccCnt; i++) {
                for(unsigned int j = 0; j < dcc[i].size(); j++) {
                    int x = dcc[i][j];
                    if(cut[x]) add(1, id[x], i, 0), add(1, i, id[x], 0);
                    bel[x] = i;
                }
                
                for(unsigned int j = 0; j < dcc[i].size(); j++) {
                    int x = dcc[i][j];
                    for(int k = head[0][x]; k; k = e[k].nxt) {
                        int y = e[k].to;
                        if(bel[y] == i) eb[e[k].id] = i;
                    }
                }
            }
            
    /*        for(int i = 1; i <= n; i++)
                printf("%d ", bel[i]);
            printf("
    ");     
            
            for(int i = 1; i <= m; i++)
                printf("%d ", eb[i]);
            printf("
    ");    */
            
            memset(dep, 0, sizeof(dep));
            memset(fa, 0, sizeof(fa));
            memset(vis, 0, sizeof(vis));
            for(int i = 1; i <= now; i++)
                if(!vis[i]) dfs(i, 0, 1);
            
            read(qn);
            for(int x, y; qn--; ) {
                read(x), read(y);
                x = eb[x], y = eb[y];
                if(x == y) puts("0");
                else printf("%d
    ", (dep[x] + dep[y] - 2 * dep[getLca(x, y)]) / 2); 
            }
        }
        return 0;
    }

    lyd给的std好难看

  • 相关阅读:
    codeforces round #433 div2
    bzoj1951
    bzoj3620
    bzoj2286
    bzoj1513
    bzoj4390
    codeforces round 430 div 2
    bzoj3339
    准备实现体积蒙皮
    看牛顿法的改进与验证局部收敛
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9466493.html
Copyright © 2020-2023  润新知