树上操作太薄弱了,根本想不出来。
思路:
首先自定义根做一遍dfs,求出sz数组,sz[i]表示i的子树大小。
在做第二遍dfs,对每一个点进行尝试,看能否为根。
当 x 点为根转移到 y 点为根时,sz发生变化,
sz[x] -= sz[y]
sz[y] += n - sz[y]
然后进行下一步搜索,回溯时改回来就好。
这道题也体现了dfs的妙处,就是回溯处理问题
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2000005;
int n, sz[maxn];
vector<int>e[maxn];
priority_queue<int>q;
void dfs1(int u, int f)
{
sz[u] = 1;
for (int v : e[u]) {
if (v == f) continue;
dfs1(v, u);
sz[u] += sz[v];
}
}
void dfs2(int u, int f)
{
// 思路:检验当前点能否为根;再换根搜索邻接点
bool flg = 0;
int t = sz[e[u][0]];
for (int v : e[u]) {
if (sz[v] != t) {
flg = 1;
break;
}
}
if (!flg) {
q.push(-u);
}
for (int v : e[u]) {
if (v == f) continue;
// change root
sz[u] -= sz[v];
sz[v] += sz[u];
dfs2(v, u);
sz[v] -= sz[u];
sz[u] += sz[v];
}
}
int main()
{
scanf("%d", &n);
if (n == 1) {
puts("1");
return 0;
}
for (int i = 1, a, b; i < n; i++) {
scanf("%d%d", &a, &b);
e[a].push_back(b);
e[b].push_back(a);
}
dfs1(1, 0);
dfs2(1, 0);
while (q.size()) {
printf("%d ", -q.top());
q.pop();
}
printf("\n");
return 0;
}
标签:sz,YsOI2020,int,dfs,P6591,dfs1,植树,push,maxn
From: https://www.cnblogs.com/CYLSY/p/17077191.html