D. Destruction of a Tree

D. Destruction of a Tree

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a tree (a graph with n vertices and n - 1 edges in which it's possible to reach any vertex from any other vertex using only its edges).

A vertex can be destroyed if this vertex has even degree. If you destroy a vertex, all edges connected to it are also deleted.

Destroy all vertices in the given tree or determine that it is impossible.

Input

The first line contains integer n (1 ≤ n ≤ 2·105) — number of vertices in a tree.

The second line contains n integers p1, p2, ..., pn (0 ≤ pi ≤ n). If pi ≠ 0 there is an edge between vertices i and pi. It is guaranteed that the given graph is a tree.

Output

If it's possible to destroy all vertices, print "YES" (without quotes), otherwise print "NO" (without quotes).

If it's possible to destroy all vertices, in the next n lines print the indices of the vertices in order you destroy them. If there are multiple correct answers, print any.

Examples

input

Copy

5
0 1 2 1 2

output

Copy

YES
1
2
3
5
4

input

Copy

4
0 1 2 3

output

Copy

NO

Note

In the first example at first you have to remove the vertex with index 1 (after that, the edges (1, 2) and (1, 4) are removed), then the vertex with index 2 (and edges (2, 3) and (2, 5) are removed). After that there are no edges in the tree, so you can remove remaining vertices in any order.

题意:给你一颗树,问你每次只删除 度为偶数 的结点,能不能将整棵树删除完?

题解:这道题需要用贪心的思维进行dfs,先处理子结点,在处理父亲节点,因为如果先处理父亲结点的话,会使子结点的度发生改变(从偶数变奇数,且不会再变化);先删除子结点,可以使父亲的结点变化(从偶数变成奇数),但其还有子节点的话,可以使度从奇数又变回偶数,所以先删除子结点是最优策略。

1>. 先dfs出从根到叶子的顺序,将其存入 stack 中(先处理子结点);

2>. 每次从栈中弹出元素,判断其度是否为偶数,if -> 是,可以将其删除,(note:如果弹出的元素的dfs序小于其dfs序是不进行处理的),这时,其子节点的度也发生了变化,继续dfs下去,判断其子结点是否能删除完。

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<bitset>
#include<iomanip>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#define eps (1e-8)
#define MAX 0x3f3f3f3f
#define u_max 1844674407370955161
#define l_max 9223372036854775807
#define i_max 2147483647
#define re register
#define pushup() tree[rt]=tree[rt<<1]+tree[rt<<1|1]
#define nth(k,n) nth_element(a,a+k,a+n);  // 将 第K大的放在k位
#define ko() for(int i=2;i<=n;i++) s=(s+k)%i // 约瑟夫
#define ok() v.erase(unique(v.begin(),v.end()),v.end()) // 排序,离散化
#define Catalan C(2n,n)-C(2n,n-1)  (1,2,5,14,42,132,429...) // 卡特兰数
using namespace std;

inline int read(){
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' & c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}

typedef long long ll;
const double pi = atan(1.)*4.;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int M=63;
const int N=5e5+5;
int du[N],v[N],per[N];    //  du --> 存度  v --> 打标机  per --> 记录其父亲结点
stack<int>ss;             //  存 dfs 序
queue<int>qq;             //  存最终的删除结果
vector<int>vect[N];       //  图

void dfs(int x,int fa){    // 得到 dfs 序列
    per[x]=fa;
    ss.push(x);
    for(int i=0;i<vect[x].size();i++){
        int u=vect[x][i];
        if(u==fa) continue;
        dfs(vect[x][i],x);
    }
    return ;
}

void dfs1(int x){      //  从 x 结点起,dfs向下,看他的子孙节点能否全部删除
    v[x]=1;
    qq.push(x); 

    for(int i=0;i<vect[x].size();i++){
        int u=vect[x][i];
        du[u]--;               //  将 x 删除,其子结点的 度 将会减少1
        if((du[u]&1)||v[u]||per[x]==u) continue;
        dfs1(u);
    }
    return ;
}
int main(){
    int n,x,rt;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        if(x==0){
            rt=i;
            continue;
        }
        else{
            vect[x].push_back(i);
            vect[i].push_back(x);
            du[x]++;
            du[i]++;
        }
    }
    if(n%2==0){
        printf("NO\n");
        return 0;
    }
    dfs(rt,0);
    memset(v,0,sizeof(v));
    while(!ss.empty()){     //  从底向上
        int d=ss.top();
        ss.pop();

        if(du[d]%2==0)
            dfs1(d);
    }
    if(qq.size()<n)
        printf("NO\n");
    else{
        printf("YES\n");
        while(!qq.empty()){
            printf("%d\n",qq.front());
            qq.pop();
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/black_horse2018/article/details/88799735