1. 程式人生 > >hdu3686Traffic Real Time Query System 圓方樹解法

hdu3686Traffic Real Time Query System 圓方樹解法

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; }