求助,80pts
查看原帖
求助,80pts
18673
ctq1999楼主2020/5/24 17:59

tt是哪个图,t是该树在环上点。

码风简洁好康,麻烦各位神仙看一下,实在不知道哪里错了= =。

还有为啥我的最后 x, y 全部要减一,但是题解不需要?

可以有偿

#include <bits/stdc++.h>

#define ll long long

using namespace std;

const int MAXN = 1000010;
const int MAXM = 100010;
const int MAXINT = 2147483647;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int n, m, k;
int ans, tot, res;

int a[MAXN];
int head[MAXN], dep[MAXN], f[MAXN][50], cnt[MAXN];
int t[MAXN], tt[MAXN], vis[MAXN], lg[MAXN], id[MAXN];
vector<int> cir[MAXN];

string s;

inline int read() {
	int s = 0, f = 1;
	char ch = getchar();
	while ('0' > ch || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
	while ('0' <= ch && ch <= '9') {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();}
	return s * f;
}

struct edge {
	int to, next;
}e[MAXN * 2];

void add_edge(int x, int y) {
	e[++tot].to = y;
	e[tot].next = head[x];
	head[x] = tot;
	return;
}

int Get_Circle(int k, int x, int fa) {
	if (vis[x]) return x;
	else vis[x] = -1;
	for (int i = head[x]; i; i = e[i].next) {
		int y = e[i].to;
		if (y == fa) continue;
		res = Get_Circle(k, y, x);
		if (res) {
			cir[k].push_back(0);
			cir[k][++cnt[k]] = x;
			id[x] = cnt[k];
			vis[x] = 1;
			return res == x ? 0 : res;
		}
	}
	return 0;
}

void dfs(int x, int fa) {
	tt[x] = !fa ? x : tt[fa];
	f[x][0] = fa;
	dep[x] = dep[fa] + 1;
	for (int i = 1; (1 << i) <= dep[x]; i++) {
		f[x][i] = f[f[x][i - 1]][i - 1];
	}
	for (int i = head[x]; i; i = e[i].next) {
		int y = e[i].to;
		if (y == fa || vis[y] == 1) continue;
		dfs(y, x);
	}
	return;
}

int Lca(int x, int y) {
	if (dep[x] < dep[y]) swap(x, y);
	while (dep[x] > dep[y]) {
		x = f[x][lg[dep[x] - dep[y]] - 1];
	}
	if (x == y) return x;
	for (int i = lg[dep[x]]; i >= 0; i--) {
		if (f[x][i] != f[y][i]) {
			x = f[x][i];
			y = f[y][i];
		}
	}
	return f[x][0];
}

int find(int x) {
	while (x != t[x]) x = t[x] = t[t[x]];
	return x;
}

bool pd(int x1, int y1, int x2, int y2) {
	if(max(x1,y1) != max(x2,y2)) return max(x1, y1) < max(x2, y2);
	if(min(x1,y1) != min(x2,y2)) return	min(x1, y1) < min(x2, y2);
	return x1 >= y1;
}

int main(){
	int q;
	scanf("%d%d", &n, &q);
	for (int i = 1; i <= n; i++) {
		t[i] = i;
		lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
	}
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		
		add_edge(a[i], i);
		t[i] = t[a[i]];
	}
	for (int i = 1; i <= n; i++) {
		int fd = find(t[i]);
		if (cnt[fd]) continue;
		cir[fd].push_back(0);
		Get_Circle(fd, i, 0);
		for (int j = 1; j <= cnt[fd]; j++) {
			dfs(cir[fd][j], 0);
		}
	}
	for (int i = 1, x, y; i <= q; i++) {
		scanf("%d%d", &x, &y);
		int fx = find(t[x]);
		int fy = find(t[y]);
		if (find(fx) != find(fy)) {
			puts("-1 -1");
			continue;
		}
		if (tt[x] == tt[y]) {
			int l = Lca(x, y);
			printf("%d %d\n", dep[x] - dep[l], dep[y] - dep[l]);
			continue;
		}
		int d1 = dep[x] + (id[tt[y]] - id[tt[x]] + cnt[fx]) % cnt[fx], d2 = dep[y] + (id[tt[x]] - id[tt[y]] + cnt[fx]) % cnt[fx];
		if (pd(dep[x], d2, d1, dep[y])) printf("%d %d\n", dep[x] - 1, d2 - 1);
		else printf("%d %d\n", d1 - 1, dep[y] - 1);
	}
	return 0;
}


2020/5/24 17:59
加载中...