洛谷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] << " ";
}