洛谷P6591 [YsOI2020]植树

这个题要你干什么,题目中已经描述的很清楚了
所以直接上思路

思路

我们定义子树大小为siz

我们可以从1号节点开始,用一种非常巧妙的方式判断

好像就是变换树根,一开始就先默认1号节点为树根

然后不断变换树根,换完之后判断一下子树的大小是不是都相同就行了

how to 变换树根

以上边这张图变成下边这张图为例, 根节点分别为1和2.

我们可以看到1点的siz就是8, 2点的siz就是3

我们把2变成根节点之后2号节点的siz加上了(siz[1] - siz[2])

而原本的siz[1] 减去的原来的siz[2]

那么式子就非常显然了.

#include <bits/stdc++.h>
#define ll long long
#define N 1000100
#define M 1010

using namespace std;
int siz[N];
int ans[N], cnt, n, add_edge, head[N << 1];
struct node {
	int next, to;
}edge[N << 1];

int read() {
	int s = 0, f = 0; char ch = getchar();
	while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

void add(int from, int to) {
	edge[++add_edge].next = head[from];
	edge[add_edge].to = to;
	head[from] = add_edge;
}

void dfs1(int x, int fa) {
	siz[x] = 1;
	for (int i = head[x]; i; i = edge[i].next) {
		int to = edge[i].to;
		if (to == fa) continue;
		dfs1(to, x), siz[x] += siz[to];
	}
}

void dfs2(int x, int fa) {
	int sy = siz[edge[head[x]].to], flag = 0;
	for (int i = head[x]; i; i = edge[i].next) {
		int to = edge[i].to;
//		if (to == fa) continue;
		if (sy != siz[to]) {
			flag = 1;
			break;
		}
	}
	if (flag == 0) ans[++cnt] = x;
	for (int i = head[x]; i; i = edge[i].next) {
		int to = edge[i].to;
		if (to == fa) continue;
		siz[x] -= siz[to];
		siz[to] += siz[x];
		dfs2(to, x);
		siz[to] -= siz[x];
		siz[x] += siz[to];
	}
}

int main() {
	n = read();
	for (int i = 1, x, y; i < n; i++) {
		x = read(), y = read();
		add(x, y), add(y, x);
	}
	dfs1(1, 1);
	dfs2(1, 1);
	sort(ans + 1, ans + cnt + 1);
	for (int i = 1; i <= cnt; i++)
		cout << ans[i] << " ";
}
posted @ 2020-07-09 08:38  Kersen  阅读(287)  评论(0)    收藏  举报