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;
    }
    
  • 相关阅读:
    日期格式设置
    ccnet编译后dll被删除
    GridView使用
    项目发布命令
    虚拟内存技术原理和使用方法
    一种可以穿透还原卡和还原软件的代码
    DataList控件也玩分页
    如何在 Windows XP 或 Windows Server 2003 的应用程序开发中实现 URL 验证
    vc 6.0中开发驱动设备程序配置方法
    通过CreateFile来读取磁盘扇区的方法
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14227258.html
Copyright © 2011-2022 走看看