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