道路相遇 圆方树,树链剖分
道路相遇
基础圆方树。
不会圆方树看我另一篇文章
发现必经之路上的点一定是简单路径上的点,可以自己手玩。处理无向图上的简单路径,考虑把圆方树建出来,发现答案就是圆方树上两点间圆点个数。由于广义圆方树上圆方点相间,可以用深度表示答案,发现答案就是\((dep[u] + dep[v] - 2 * dep[lca]) / 2 + 1\),lca树剖求。
#include <cstdio>
#include <cctype>
#include <vector>
#define R register
#define I inline
#define B 10000000
using namespace std;
const int N = 1000003;
char buf[B], *p1, *p2;
I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; }
I int rd() {
R int f = 0; R char c = gc();
while (c < 48 || c > 57)
c = gc();
while (c > 47 && c < 58)
f = f * 10 + (c ^ 48), c = gc();
return f;
}
int s[N], S[N], vis[N], dfn[N], low[N], sta[N], fa[N], dep[N], siz[N], son[N], top[N], tim, cnt, stp;
vector <int> g[N], G[N];
I int min(int x, int y) { return x < y ? x : y; }
I void swap(int &x, int &y) { x ^= y, y ^= x, x ^= y; }
void dfs(int x) {
vis[sta[++stp] = x] = 1, dfn[x] = low[x] = ++tim;
for (R int i = 0, y ,z; i < s[x]; ++i)
if (!dfn[y = g[x][i]]) {
dfs(y), low[x] = min(low[x], low[y]);
if (low[y] >= dfn[x]) {
G[++cnt].push_back(x), G[x].push_back(cnt);
do {
vis[z = sta[stp--]] = 0, G[cnt].push_back(z), G[z].push_back(cnt);
} while (z ^ y);
}
}
else
low[x] = min(low[x], dfn[y]);
}
void dfs1(int x, int f) {
fa[x] = f, dep[x] = dep[f] + 1, siz[x] = 1;
for (R int i = 0, y, m = 0; i < S[x]; ++i)
if ((y = G[x][i]) ^ f) {
dfs1(y, x), siz[x] += siz[y];
if (siz[y] > m)
m = siz[y], son[x] = y;
}
}
void dfs2(int x, int r) {
top[x] = r;
if (son[x])
dfs2(son[x], r);
for (R int i = 0, y; i < S[x]; ++i)
if ((y = G[x][i]) ^ fa[x] && y ^ son[x])
dfs2(y, y);
}
I int query(int x, int y) {
R int o = dep[x] + dep[y];
while (top[x] ^ top[y]) {
if (dep[top[x]] < dep[top[y]])
swap(x, y);
x = fa[top[x]];
}
if (dep[x] > dep[y])
swap(x, y);
return ((o - (dep[x] << 1)) >> 1) + 1;
}
int main() {
R int n = rd(), m = rd(), Q, i, x, y;
for (i = 1; i <= m; ++i)
x = rd(), y = rd(), g[x].push_back(y), g[y].push_back(x);
for (i = 1; i <= n; ++i)
s[i] = g[i].size();
Q = rd(), cnt = n, dfs(1);
for (i = 1; i <= cnt; ++i)
S[i] = G[i].size();
dfs1(1, 0), dfs2(1, 1);
for (i = 1; i <= Q; ++i)
x = rd(), y = rd(), printf("%d\n", query(x, y));
return 0;
}