• 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;
    }
    
  • 相关阅读:
    企业管理:“残缺”也是一种美?
    销售到出仓所经历的表
    采购到入库所经历的表
    OM 订单状态
    OM客户、客户地点
    接收事务处理类型 rcv_transactions
    安装ORACLE不能安装解决方法
    系统变量设置
    如何取分组最大值记录
    CentOS (Linux) 上开启FTP服务并配置用户
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14227258.html
Copyright © 2020-2023  润新知