CF 964D Destruction Of A Tree 思维,set

本文介绍了一种针对树形结构的数据操作算法,探讨了如何通过特定的操作序列删除所有节点。该算法首先判断树的节点数量,对于奇数节点的情况,提出了一种有效的递归删除策略,最终实现了树的完全清除并输出操作步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:n个节点的树,操作:删除度数为偶数的顶点以及他所有的边.
n<=1e5,问是否能通过操作把所有节点都删除,若能输出操作序列,否则输出NO.


每次删除偶数度的顶点,也就是每次删除某个点其偶数个边.
若顶点数为偶数,那么有奇数条边 永远会有一条边不会被删除,此时肯定无解.


若顶点数为奇数,那么至少有一个点的度为偶数 (因为总的度数为偶数),此时一定有解.
要想删叶子节点 就必须删掉其父节点.

顺着叶子往上找到第一个度数为偶数的点u,此时u的子树中所有的点的度都为奇数.
那么此时删除u.u的儿子度数都变为偶数.不断往下 可以删除整个子树u.

不断在u的上部分(偶数个边)找到深度最深得偶数度顶点.set维护偶数度的二元组(dep[u],u)即可.

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> ii;
const int N=2e5+5;
int n,u,v,rt,deg[N],dep[N];
bool vis[N];
vector<int> e[N];
void dfs(int u,int fa,int level)
{
	dep[u]=level;
	for(int i=0;i<e[u].size();i++)
		if(e[u][i]!=fa)
			dfs(e[u][i],u,level+1); 
}
int main()
{
	//ios::sync_with_stdio(false);
	//cin.tie(0);
	scanf("%d",&n);
	for(int u=1;u<=n;u++)
	{
		scanf("%d",&v);
		if(v==0)
			rt=u;
		else
		{
			e[v].push_back(u); 
			e[u].push_back(v);
			deg[u]++,deg[v]++;
		}
	}
	if(n%2==0)
	{
		puts("NO");
		return 0;
	}
	puts("YES");
	dfs(rt,0,0);
	set<ii> s;
	for(int i=1;i<=n;i++)
		if(deg[i]%2==0)
			s.emplace(ii(-dep[i],i));;
	while(!s.empty())
	{
		ii t=*s.begin();
		s.erase(s.begin());
		int u=t.second;
		printf("%d\n",u);
		vis[u]=true;
		for(int i=0;i<e[u].size();i++)
		{
			int v=e[u][i];
			if(vis[v])	continue;
			deg[v]--;
			if(deg[v]%2==0)
				s.emplace(ii(-dep[v],v));
			else
				s.erase(s.find(ii(-dep[v],v)));
		}	
	}
	return 0;
}
//7
//0 1 2 3 3 3 1


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值