hdu3686Traffic Real Time Query System 圆方树解法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvzelong2014/article/details/83315888

hdu3686Traffic Real Time Query System

题目传送门

分析

题目大意:给定一张无向图,每次给两条边,求从一条边走到另一条边的必经点个数。
这么好的一道圆方树模板居然都写缩点!
处理点双的时候新开一个边的栈,同时弹栈,这样可以处理出每条边所属的方点。
图上两点的必经点       \iff 图上两点间的割点       \iff 两点间圆方树上圆点个数。
那么边的话就是两条边所属的点双的方点之间的圆点个数啊。
然后就分分钟上板子啊。

代码

#include<bits/stdc++.h>
const int N = 4e5 + 10, M = 4e5 + 10;
int ri() {
    char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f  = -1;
    for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int tot, n, x[M], be[M], C; bool vis[M];
struct Edge {
    int to[M], nx[M], pr[N], tp; Edge() {tp = 1;}
    void Clr() {memset(pr, 0, sizeof(pr)); tp = 1;}
    void add(int u, int v) {to[++tp] = v; nx[tp] = pr[u]; pr[u] = tp;}
    void adds(int u, int v) {add(v, u); add(u, v);} 
};
struct Round_Square_Tree {
    Edge T; int sz[N], fa[N], de[N], d[N], ds[N], di[N];
    void Clr() {T.Clr(); memset(ds, 0, sizeof(ds));}
     void dfs1(int u, int ff) {
        fa[u] = ff; de[u] = de[ff] + 1; sz[u] = 1; di[u] = di[ff] + (u <= n);
        for(int i = T.pr[u], v; i; i = T.nx[i]) 
        if((v = T.to[i]) != ff)
            dfs1(v, u), sz[u] += sz[v], sz[ds[u]] < sz[v] ? ds[u] = v : 0;
    }
    void dfs2(int u, int c) {
        d[u] = c; if(!ds[u]) return ; dfs2(ds[u], c);
        for(int i = T.pr[u]; i; i = T.nx[i]) 
            if(T.to[i] != ds[u] && T.to[i] != fa[u]) 
                dfs2(T.to[i], T.to[i]);
    }
    int Lca(int u, int v) {
        for(;d[u] != d[v]; u = fa[d[u]]) de[d[u]] < de[d[v]] ? u ^= v ^= u ^= v : 0;
        return de[u] < de[v] ? u : v;
    }
    int Query(int u, int v) {
        int x = Lca(u, v); 
        return di[u] + di[v] - (di[x] << 1) + (x <= n);
    }
}rst;
struct Tarjan {
    Edge G; int dfn[N], low[N], st[N], tp, tm;
    void Clr() {
        memset(dfn, 0, sizeof(dfn));
        memset(low, 0, sizeof(low));
        memset(vis, 0, sizeof(vis));
        G.Clr(); C = tp = tm = 0;
    }
    void dfs(int u) {
        dfn[u] = low[u] = ++tm; st[++tp] = u;
        for(int i = G.pr[u], v; i; i = G.nx[i]) if(!vis[i]) {
            vis[i] = vis[i ^ 1] = true; x[++C] = i >> 1; v = G.to[i];
            if(!dfn[v]) {
                dfs(v), low[u] = std::min(low[u], low[v]); 
                if(low[v] >= dfn[u]) {
                    for(rst.T.adds(u, ++tot); st[tp + 1] != v;)
                        rst.T.adds(st[tp--], tot);
                    for(;x[C + 1] != i >> 1;) be[x[C--]] = tot;
                }
            }
            else low[u] = std::min(low[u], dfn[v]);
        }
    }
}tar;
int main() {
    for(;1;) {
        tot = n = ri(); int m = ri(); 
        if(!n && !m) break; tar.Clr(); rst.Clr();
        for(;m--;) tar.G.adds(ri(), ri());
        for(int i = 1;i <= n; ++i) if(!tar.dfn[i]) tar.dfs(i), rst.dfs1(i, 0), rst.dfs2(i, i);
        for(int q = ri(), x, y;q--;) x = ri(), y = ri(), printf("%d\n", rst.Query(be[x], be[y]));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lvzelong2014/article/details/83315888
今日推荐