题意:给出一颗树,每次可以删除任意一个度数为偶数的节点,问是否可以将所有节点删完?
题解:每次只能删度数为偶数的节点,故每次只能减少偶数条边,所以只有奇数点的树可以被删完。先用DFS扫一遍,将每个点的子树的节点数处理出来,然后跑DFS,先只跑偶数点的子树个数,跑到底,如果此点不可被删则返回FALSE,否则删除此点继续后继续往下跑。
#include <bits/stdc++.h>
using namespace std;
const double EPS = 1e-8;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 10;
int n, deg[maxn], sz[maxn];
vector<int> g[maxn], ans;
void DFS_sz(int u, int fa)
{
sz[u]++;
for(int i = 0, n = g[u].size(); i < n; i++){
int to = g[u][i];
if(to != fa){
DFS_sz(to, u);
sz[u] += sz[to];
}
}
}
bool DFS(int u, int fa)
{
for(int i = 0, n = g[u].size(); i < n; i++){
int to = g[u][i];
if(to!=fa && sz[to] % 2 == 0){
if(!DFS(to, u)) return false;
deg[u]--;
}
}
if(deg[u] & 1) return false;
ans.push_back(u);
for(int i = 0, n = g[u].size(); i < n; i++){
int to = g[u][i];
if(to != fa && sz[to] % 2 == 1){
deg[to]--;
if(!DFS(to, u)) return false;
}
}
return true;
}
int main()
{
scanf("%d", &n);
for(int i = 1, pa; i <= n; i++){
scanf("%d", &pa);
if(pa != 0){
g[i].push_back(pa);
g[pa].push_back(i);
deg[i]++; deg[pa]++;
}
}
DFS_sz(1, -1);
if(DFS(1, -1)){
puts("YES");
for(int v = 0, n = ans.size(); v < n; v++) printf("%d\n", ans[v]);
}
else puts("NO");
return 0;
}