UVA1464 题解

题目链接

将图建成圆方树后会发现,必经点数 = 圆方树上两点路径上圆点数。

考虑求路径中的圆点数量。因为起点和终点均为圆点,所以路径 \(x\)\(y\) 的答案即为 \((dis(x,y)+1)/2\)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int N = 200005;
const int INF = 0x3f3f3f3f;
int n, m;
int dfn[N], low[N], ck, cnt;
vector<int> G[N], H[N];
stack<int> s;
int vis[N], tot;
void tarjan(int u, int fa) {
	dfn[u] = low[u] = ++ck;
	vis[u] = tot;
	s.push(u);
	for (auto v : G[u]) {
		if (!dfn[v]) {
			tarjan(v, u);
			low[u] = min(low[u], low[v]);
			if (low[v] >= dfn[u]) {
				cnt++;
				while (1) {
					int x = s.top();
					s.pop();
					H[cnt].push_back(x);
					H[x].push_back(cnt);
					if (x == v) break;
				}
				H[cnt].push_back(u);
				H[u].push_back(cnt);
			}
		} else if (v != fa){
			low[u] = min(low[u], dfn[v]);
		}
	}
}
int dep[N], fa[N], sz[N], son[N], top[N];
void dfs1(int u) {
	dfn[u] = ++ck;
	dep[u] = dep[fa[u]] + 1;
	sz[u] = 1;
	for (auto v : H[u]) {
		if (v == fa[u]) continue;
		fa[v] = u;
		dfs1(v);
		sz[u] += sz[v];
		if (sz[v] > sz[son[u]]) son[u] = v;
	}
}
void dfs2(int u, int h) {
	top[u] = h;
	if (son[u]) dfs2(son[u], h);
	for (auto v : H[u]) {
		if (v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
}
int LCA(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}
	return dep[x] < dep[y] ? x : y;
}
int dis(int x, int y) {
	if (vis[x] != vis[y]) return 0;
	int ans = dep[x] + dep[y] - 2 * dep[LCA(x, y)];
	ans = ans / 2 - 1;
	return ans;
}
struct Node {
	int x, y;
} bian[N];
int a[N];
int main() {
	while (scanf("%d%d", &n, &m) != EOF) {
		if (n == 0 && m == 0) break;
		while (!s.empty()) {
			s.pop();
		}
		for (int i = 1; i < N; i++) {
			dfn[i] = low[i] = 0;
			dep[i] = fa[i] = son[i] = sz[i] = top[i] = 0;
			vis[i] = 0;
			G[i].clear();
			H[i].clear();
		}
		ck = 0;
		tot = 0;
		for (int i = 1; i <= m; i++) {
			int u, v;
			scanf("%d%d", &u, &v);
			G[u].push_back(v);
			G[v].push_back(u);
			bian[i] = {u, v};
		}
		cnt = n;
		for (int i = 1; i <= n; i++) {
			if (!dfn[i]) {
				tot++;
				vis[i] = 1;
				tarjan(i,-1);
				dfs1(i);
				dfs2(i, i);
			}
		}
		ck = 0;
		int q;
		scanf("%d", &q);
		while (q--) {
			int x, y;
			scanf("%d%d", &x, &y);
			int a = bian[x].x, b = bian[x].y, c = bian[y].x, d = bian[y].y;
			int ans = max(max(dis(b, d), dis(a, d)), max(dis(b, c), dis(a, c)));
			// printf("#%d\n", LCA(a, b));
			printf("%d\n", ans);
		}
	}
	return 0;
}
posted @ 2025-03-09 21:23  jxy2012  阅读(21)  评论(0)    收藏  举报
//雪花飘落效果