对于能不能拆除一棵树,首先从根节点考虑,根节点必须等父亲先拆除,父亲的所有边若为偶则可先拆父亲,否则要先拆父亲的父亲,如此递归实现即可。
然后在递归过程建立先拆后拆的边,之后就是一个dag的点排序问题,用一个vector即可实现。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 201010;
vector<int> son[maxn] , nex[maxn];
int n;
vector<int> ans;
int pre[maxn];
int dfs(int u , int fa){
int all = 0;
if(fa!=0)
++all;
for(int i =0;i<son[u].size();i++) if(son[u][i]!=fa){
int add = dfs(son[u][i],u);
all += add;
if(add) {
nex[u].push_back(son[u][i]);
++pre[son[u][i]];
} else {
nex[son[u][i]].push_back(u);
++pre[u];
}
}
if(all % 2 == 0)
return 0;
return 1;
}
queue<int> now;
void cal(){
for(int i=1;i<=n;i++)
if(pre[i] == 0) now.push(i);
while(!now.empty()){
int u = now.front();
now.pop();
printf("%d\n",u);
for(int i =0;i<nex[u].size();i++){
--pre[nex[u][i]];
if(!pre[nex[u][i]]) {
now.push(nex[u][i]);
}
}
}
}
int main()
{
scanf("%d",&n);
int root;
for(int i=1;i<=n;i++) son[i].clear(),nex[i].clear(),pre[i]=0;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
if(x > 0) {
son[x].push_back(i),son[i].push_back(x);
}
else root = i;
}
int ans = dfs(root , 0);
if(ans == 0) printf("YES\n");
else printf("NO\n");
if(ans == 0) cal();
return 0;
}