luoguP4320 道路相遇 圆方树
Posted ReMoon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP4320 道路相遇 圆方树相关的知识,希望对你有一定的参考价值。
标题已经告诉你怎么做了.....
两点间的圆点个数即为所求
建出圆方树后打个树剖求$lca$就行.....
复杂度$O(n + q \\log n)$
#include <cstdio> #include <cstring> #include <iostream> using namespace std; extern inline char gc() { static char RR[23456], *S = RR + 23333, *T = RR + 23333; if(S == T) fread(RR, 1, 23333, stdin), S = RR; return *S ++; } inline int read() { int p = 0, w = 1; char c = gc(); while(c > \'9\' || c < \'0\') { if(c == \'-\') w = -1; c = gc(); } while(c >= \'0\' && c <= \'9\') p = p * 10 + c - \'0\', c = gc(); return p * w; } int wr[50], rw; #define pc(o) *O ++ = o char WR[40000005], *O = WR; inline void write(int x) { if(!x) pc(\'0\'); if(x < 0) pc(\'-\'), x = -x; while(x) wr[++ rw] = x % 10, x /= 10; while(rw) pc(wr[rw --] + \'0\'); pc(\'\\n\'); } #define ri register int #define sid 500050 #define nid 1005000 #define eid 4005000 int n, m, cnp; int cap[sid], aap[nid], nxt[eid], node[eid]; inline void cop(int u, int v) { nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v; } inline void bop(int u, int v) { nxt[++ cnp] = aap[u]; aap[u] = cnp; node[cnp] = v; } int st[sid], snp, scc; int dfn[sid], low[sid], dfn_id; #define cur node[i] void tarjan(int o) { st[++ snp] = o; dfn[o] = low[o] = ++ dfn_id; for(int i = cap[o]; i; i = nxt[i]) if(!dfn[cur]) { tarjan(cur); low[o] = min(low[o], low[cur]); if(low[cur] < dfn[o]) continue; int e; ++ scc; bop(o, scc); do { e = st[snp --]; bop(scc, e); } while(e != cur); } else low[o] = min(low[o], dfn[cur]); } int anc[nid], fa[nid], sz[nid]; int dep[nid], de[nid], son[nid]; void dfs(int o) { sz[o] = 1; de[o] = de[fa[o]] + (o <= n); for(int i = aap[o]; i; i = nxt[i]) if(cur != fa[o]) { dep[cur] = dep[o] + 1; fa[cur] = o; dfs(cur); sz[o] += sz[cur]; if(sz[son[o]] < sz[cur]) son[o] = cur; } } void dfs(int o, int tp) { anc[o] = tp; if(!son[o]) return; dfs(son[o], tp); for(int i = aap[o]; i; i = nxt[i]) if(cur != fa[o] && cur != son[o]) dfs(cur, cur); } int lca(int u, int v) { int pu = anc[u], pv = anc[v]; while(pu != pv) { if(dep[pu] < dep[pv]) swap(u, v), swap(pu, pv); u = fa[pu]; pu = anc[u]; } return (dep[u] < dep[v]) ? u : v; } int main() { scc = n = read(); m = read(); for(ri i = 1; i <= m; i ++) { int u = read(), v = read(); cop(u, v); cop(v, u); } tarjan(1); dfs(1); dfs(1, 1); int q = read(); for(ri i = 1; i <= q; i ++) { int u = read(), v = read(), o = lca(u, v); write(de[u] + de[v] - de[o] - de[fa[o]]); } fwrite(WR, 1, O - WR, stdout); return 0; }
以上是关于luoguP4320 道路相遇 圆方树的主要内容,如果未能解决你的问题,请参考以下文章