zoukankan      html  css  js  c++  java
  • codeforces 963B Destruction of a Tree

    B. 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.

     

    题意:

    给出一棵树,每次可以删除一个度数为偶的点 和 与这个点相连的边。

    问是否存在一种方案吧整个树都删除,如果存在,输出任意方案。

    题解:

    分析:叶节点一定是不能直接删掉的(度数为1),因此要想删掉叶节点,必须先删掉其父节点。

    如果父节点的度数为偶,则可以将其删去,

    如果父节点的度数为奇,那么要想删掉该父节点,必须先删掉此父节点的父节点………………

     

    是不是有一点向根递归的感觉。

    刚才遗漏了很多细节,现在来完善这个思路:

    设一个节点的子节点中,度数为奇的子节点数量为cnt[0],度数为偶的子节点数量为cnt[1]

    这个节点的度数deg=cnt[0]+cnt[1]+1

    度数为偶的子节点要首先删掉的,那么该节点剩下的度数就是deg-cnt[1]

    如果(deg-cnt[1])%2==0,那么这个点也可以直接删掉。

    如果(deg-cnt[1])%2==1,那么这个点不能直接删掉,需要先删掉其父节点。

    那么一个有意思的树形dp就出来了,v[i]表示将 i 的子节点中能直接删掉的删掉后,i 能否直接删掉(v[i]==0表示不能,v[i]==1表示能)。

     

    最后看v[root]是否为1就可以判断yes,no。

    输出方案:

    对于一个节点,先删除其子节点中能直接删除的,然后将这个节点删除,这样其不能删除的子节点就可以删除了,将其删除。

    递归处理,输出即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<ctime>
     5 #include<cstdlib>
     6 #include<algorithm>
     7 #include<cmath>
     8 #include<string>
     9 using namespace std;
    10 int read(){
    11     int xx=0,ff=1;char ch=getchar();
    12     while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
    13     while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
    14     return xx*ff;
    15 }
    16 const int maxn=200010;
    17 int N,root;
    18 int lin[maxn],len,deg[maxn];
    19 struct edge{
    20     int y,next;
    21 }e[maxn<<1];
    22 inline void insert(int xx,int yy){
    23     e[++len].next=lin[xx];
    24     lin[xx]=len;
    25     e[len].y=yy;
    26     deg[xx]++;
    27 }
    28 bool v[maxn];//v==1:can delete now,v==0:can not delete now
    29 int cnt[maxn][2];
    30 bool dfs(int x,int fa){
    31     for(int i=lin[x];i;i=e[i].next)
    32         if(e[i].y!=fa)
    33             cnt[x][dfs(e[i].y,x)]++;
    34     if((deg[x]-cnt[x][1])%2==0)
    35         v[x]=1;
    36     else
    37         v[x]=0;
    38     return v[x];
    39 }
    40 void print(int x,int fa){
    41     for(int i=lin[x];i;i=e[i].next)
    42         if(e[i].y!=fa)
    43             if(v[e[i].y])
    44                 print(e[i].y,x);
    45     printf("%d
    ",x);
    46     for(int i=lin[x];i;i=e[i].next)
    47         if(e[i].y!=fa)
    48             if(!v[e[i].y])
    49                 print(e[i].y,x);
    50 }
    51 int main(){
    52     //freopen("in.txt","r",stdin);
    53     N=read();
    54     for(int i=1;i<=N;i++){
    55         int temp=read();
    56         if(!temp)
    57             root=i;
    58         else
    59             insert(i,temp),insert(temp,i);
    60     }
    61     if(dfs(root,0)){
    62         puts("YES");
    63         print(root,0);
    64     }
    65     else
    66         puts("NO");
    67     return 0;
    68 }
    View Code
  • 相关阅读:
    暂存。2
    暂存。
    dom兼容性问题3 元素操作
    一个查看Access数据库密码的工具
    解除IIS配置节锁定
    解决cef中title不现实tooltip的问题
    创建.symlnk文件
    查询orcale运行的SQL语句记录
    跨域http头
    C#抓取天气数据
  • 原文地址:https://www.cnblogs.com/lzhAFO/p/8884155.html
Copyright © 2011-2022 走看看