zoukankan      html  css  js  c++  java
  • CF963B Solution

    题目链接

    题解

    下文将有偶数个节点的树称之为“偶树”,而奇数个结点的树称之为“奇树”。

    如果输入的树为偶树,一定无法全部摧毁,因为(n-1)为奇数而每次删去偶数条边。同样,在删点过程中,森林中的每棵树一定只能为奇树。因此如果要删去一棵树的根节点(设编号为1的点为根节点),必须保证这颗树的全部子树都为奇树。而对于偶子树,我们需要递归直至一个节点的子树全部为奇树时才可将其删去。总结一下,对于每一个根节点,需要依次执行3个操作:1. 递归删去所有偶子树;2.删去根节点;3.递归奇子树。

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int fst[N],nxt[2*N],v[2*N],cnt;
    int siz[N],ans[N],pos;//siz[i]:以编号为i的节点为根的子树大小
    void add(int a,int b)
    {
    	v[++cnt]=b;
    	nxt[cnt]=fst[a]; fst[a]=cnt;
    }
    void dfs1(int x)//计算子树大小
    {
    	siz[x]=1;
    	for(int i=fst[x];i;i=nxt[i])
    	{
    		int y=v[i];
    		if(siz[y]) continue;
    		dfs1(y); siz[x]+=siz[y];
    	}
    }
    void dfs2(int x,int fa)
    {
        //递归删去偶子树
    	for(int i=fst[x];i;i=nxt[i])
    	{
    		int y=v[i];
    		if(y!=fa && siz[y]%2==0) dfs2(y,x);
    	}
        //删去根节点
    	ans[++pos]=x;
        //递归奇子树
    	for(int i=fst[x];i;i=nxt[i])
    	{
    		int y=v[i];
    		if(y!=fa && siz[y]%2) dfs2(y,x);
    	}
    }
    int main()
    {
    	int n,p;
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&p);
    		if(p) {add(i,p); add(p,i);}
    	}
    	if(n%2==0) {printf("NO"); return 0;}
    	dfs1(1); dfs2(1,0);
    	printf("YES
    ");
    	for(int i=1;i<=pos;i++) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    UVALive 7509 Dome and Steles
    HDU 5884 Sort
    Gym 101194H Great Cells
    HDU 5451 Best Solver
    HDU 5883 The Best Path
    HDU 5875 Function
    卡特兰数
    UVa 11729 Commando War 突击战
    UVa 11292 The Dragon of Loowater 勇者斗恶龙
    Spark Scala Flink版本对应关系
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14227258.html
Copyright © 2011-2022 走看看