记录编号 577439 评测结果 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
题目名称 [POI 2012][BZOJ 2791]会合(Rendezvous) 最终得分 100
用户昵称 GravatarHeSn 是否通过 通过
代码语言 C++ 运行时间 8.405 s
提交时间 2022-11-03 21:50:42 内存使用 66.78 MiB
显示代码纯文本
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 500010;
int n, m, inc[MAXN], stp[MAXN], num[MAXN], len[MAXN], dep[MAXN], f[20][MAXN], bel[MAXN], cnt;
vector<int> cd[MAXN];
void dfs(int x, int fa, int rt, int d) {
	bel[x] = rt;
	dep[x] = d;
	for(int i = 0; i < cd[x].size(); i ++) {
		int u = cd[x][i];
		if(inc[u] || u == fa) {
			continue;
		}
//		dep[u] = dep[x] + 1;
		dfs(u, x, rt, d + 1);
	}
}
int lca(int x, int y) {
	if(dep[x] < dep[y]) {
		swap(x, y);
	}
	for(int i = 20; i >= 0; i --) {
		int u = f[i][x];
		if(dep[u] >= dep[y]) {
			x = u;
		}
	}
	if(x == y) {
		return x;
	}
	for(int i = 20; i >= 0; i --) {
		int u = f[i][x], v = f[i][y];
		if(u != v) {
			x = u;
			y = v;
		}
	}
	return f[0][x];
}
void find_circle(int x, int id, int s) {
    if(stp[x]) {
    	return ;
	}
    num[x] = id;
	len[id] ++;
	stp[x] = s;
    find_circle(f[0][x], id, s + 1);
}
int check(int a, int b, int c, int d) {
	if(max(a, b) != max(c, d)) {
		return max(a, b) < max(c, d);
	}
    if(min(a, b) != min(c, d)) {
    	return min(a, b) < min(c, d);
	}
	return a >= b;
}
signed main() {
    freopen("rdz.in", "r", stdin);
    freopen("rdz.out", "w", stdout);
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) {
		int x;
		scanf("%d", &x);
		f[0][i] = x;
		cd[x].push_back(i);
		inc[x] ++;
	}
	queue<int> q;
	for(int i = 1; i <= n; i ++) {
		if(!inc[i]) {
			q.push(i);
		}
	}
	while(!q.empty()) {
		int x = q.front();
		q.pop();
		int u = f[0][x];
		inc[u] --;
		if(!inc[u]) {
			q.push(u);
		}
	}
	for(int i = 1; i <= 20; i ++) {
		for(int j = 1; j <= n; j ++) {
			f[i][j] = f[i - 1][f[i - 1][j]];
		}
	}
	for(int i = 1; i <= n; i ++) {
		if(inc[i]) {
			dfs(i, 0, i, 0);
			if(!stp[i]) {
				find_circle(i, ++ cnt, 1);
			}
		}
	}
	for(int i = 1; i <= m; i ++) {
		int x, y;
		scanf("%d%d", &x, &y);
//		cout << "      ";
//		cout << "      ";
		if(num[bel[x]] != num[bel[y]]) {
			printf("-1 -1\n");
		}
		else if(bel[x] == bel[y]) {
			int w = lca(x, y);
			printf("%d %d\n", dep[x] - dep[w], dep[y] - dep[w]);
		}
		else {
//			cout << 11111 << ' ';
			int u = bel[x], v = bel[y];
            int ans1 = dep[x] + (stp[v] - stp[u] + len[num[u]]) % len[num[u]];
			int ans2 = dep[y] + (stp[u] - stp[v] + len[num[u]]) % len[num[u]];
//			cout << ans1 << ' ' << ans2 << ' ';
			if(check(dep[x], ans2, ans1, dep[y])) {
				printf("%d %d\n", dep[x], ans2);
			}
            else {
				printf("%d %d\n", ans1, dep[y]);
			}
		}
	}
	return 0;
}