zoukankan      html  css  js  c++  java
  • 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好难看

  • 相关阅读:
    PHP实现无限极分类
    html2canvas生成并下载图片
    一次线上问题引发的过程回顾和思考,以更换两台服务器结束
    Intellij IDEA启动项目报Command line is too long. Shorten command line for XXXApplication or also for
    mq 消费消息 与发送消息传参问题
    idea 创建不了 java 文件
    Java switch 中如何使用枚举?
    Collections排序
    在idea 设置 git 的用户名
    mongodb添加字段和创建自增主键
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9466493.html
Copyright © 2011-2022 走看看