CF963B

题意:每次消除度数为偶数的叶子节点以及它所有的边,问这个树能否被消除完,能消除完需要输出消除的顺序

做法:处理dfs序,用栈记录,先消除dfs序大的,若先消除根节点,其叶子节点要是无法消除就wa了,所以贪心消除最靠近叶子的节点

注意:注意度数为0也是偶数

代码:

#include<cstdio>
#include<stack>
#define maxn 200005
using namespace std;
int n,fa[maxn],deg[maxn],vis[maxn],head[maxn],tot;
stack<int>sta;
int ans[maxn],num;//记录答案 
struct edge{int to,next;}e[maxn<<1];
inline void add(int u,int v){e[++tot] = (edge){v,head[u]};head[u] = tot;}
inline int read(){
    int x=0; char c=std::getchar();
    while(c<'0'||c>'9')c=std::getchar();
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=std::getchar();}
    return x;
}
void dfs1(int x,int f){//处理dfs序 
    fa[x] = f; sta.push(x);
    for(int i = head[x];i;i = e[i].next){
        int v = e[i].to;
        if(v == f) continue;
        dfs1(v,x);
    }
}
void dfs2(int x){
    vis[x] = 1; ans[++num] = x;
    for(int i = head[x];i;i = e[i].next){
        int v = e[i].to; deg[v] --;
        if(v == fa[x] || vis[v]) continue;
        if(!(deg[v] & 1)) dfs2(v);
    }
}
int main(){
    n = read(); int v;
    for(int i = 1;i <= n;i++){
        v = read();
        if(v){
        add(i,v); add(v,i);
        ++deg[v]; ++deg[i]; 
        }
    }
    dfs1(1,-1);
    while(!sta.empty()){
        int az = sta.top();
        sta.pop();
        if(!(deg[az] & 1)) dfs2(az);
    }
    if(num == n){ puts("YES");
        for(int i = 1;i <= num;i++)
        printf("%d
",ans[i]);
    }
    else puts("NO");
    return ~~(0^0)*(0^0);
}