CF963B Destruction of a Tree 题解

这篇具有很好参考价值的文章主要介绍了CF963B Destruction of a Tree 题解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

CF963B Destruction of a Tree 题解

  洛谷题目链接

  这里提供一个较为朴素的 DP 想法。

题意简述

  给定一棵树,节点个数不超过 \(2 \times 10^5\),每次可以删掉度数为偶数的点。问最后能不能删完;能删完给出删除方案。

思路分析

  首先可以随便选一个点作为根。

  其次,我们考虑在一棵子树的删除情况,我们令根节点为 \(u\),它的直接儿子为 \(v_1,v_2 \dots v_k\)。考虑根节点的删除情况,以及删除时需要参考什么东西。我们发现,根节点删除分为两种情况:1.它的父节点被删除了,也就是这颗子树没有(根节点的)“支上去”的那条边;2.它的父节点还没删除,我就删除根节点。此时是有“支上去”的那条边的。

  于是,我们令 \(f_{u,t} ,t \in \{0,1\}\)\(f_{u,0}\) 表示没有“支上去”的那条边的时候,是否可以删除;\(f_{u,1}\) 表示有“支上去”的那条边的时候,是否可以删除。根据定义, \(f_{u,t} \in \{0,1\}\) ,即状态表示的是“不可以”或者“可以”。

  我们考虑子树内如何合理安排删除。我们假设我们现在已经知道了所有 \(v_i,(1 \le i \le k)\)\(f_{v_i,0}\)\(f_{v_i,1}\) 结果。首先,如果存在 \(f_{v_i,0} = 0\)\(f_{v_i,1} = 0\),那么显然无论如何安排删除顺序,也不能保证删除成功。

  接下来我们分析如何安排删除顺序。我们发现,对于 \(f_{v_i,0} = 0\)\(f_{v_i,1} = 1\) 的子节点,应当先删掉它所在的那颗子树(因为要保留 \(u\)\(v_i\) 的那条边的时候才能删)。对于 \(f_{v_i,0} = 1\)\(f_{v_i,1} = 0\) 的节点,我们必须在删掉 \(u\) 之后删。对于\(f_{v_i,0} = 1\)\(f_{v_i,1} = 1\) 的节点,随便安排。

  然后我们考虑根节点如何删除。我们发现,如果删掉前面必须删的那些点后,根节点剩下的边是偶数条,那就删掉,然后 \(f_{u,0} \gets 1\) 即可。但是这里就有一个问题,假如说我们剩奇数条边的时候,我们可以再先删掉一个 \(f_{v_i,0} = 1\)\(f_{v_i,1} = 1\) 的节点来使得度数变成偶数。于是这里要再判断一下。

  奇数的时候同理,注意“支上去”的边也是连在根节点上的,所以对应的,\(f_{u,1} \gets 1\)

  具体实现的时候,我们不妨把一个点的子节点按照 \(f_{v_i,0} = 0\)\(f_{v_i,1} = 1\)的节点在前面,\(f_{v_i,0} = 1\)\(f_{v_i,1} = 1\)的节点在中间,\(f_{v_i,0} = 1\)\(f_{v_i,1} = 0\)的节点在后面,以此来排序。

  输出方案的时候,我们可以对于每个点,搜索对应状态(比如根节点是1,从\(f_{1,0}\)开始搜索),再递归下去(对于\(f_{v_i,0} = 1\)\(f_{v_i,1} = 1\)的节点,我们随便钦定一个就行)。所以一共是两遍dfs,第一遍求状态,第二遍根据状态信息推出顺序。第二遍dfs的时候,代码中的分类有所简化,如果不清楚,可以尝试先各类写一遍再简化合并。文章来源地址https://www.toymoban.com/news/detail-711592.html

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 2e5 + 5;

struct edge
{
	int v,next;
}e[N*2];

int head[N];
int cnt;

void adde(int u,int v)
{
	++cnt;
	e[cnt].v =v;
	e[cnt].next = head[u];
	head[u] = cnt;
}

int n;
bool f[N][2];
vector<int> output;

struct node
{
	int idx;
	bool ck0,ck1;
};

bool cmp1(const node xx,const node yy)
{
	if(xx.ck1 != yy.ck1)
		return xx.ck1 > yy.ck1;
	return xx.ck0 < yy.ck0;
}

vector<node> vec[N];
int deg[N];
int tdx[N];

bool dfs(int u,int fa)
{
	bool check = true;
	for(int i = head[u];i != 0;i = e[i].next)
	{
		int v = e[i].v;
		if(v != fa)
		{
			deg[u]++;
			dfs(v,u);
			if(f[v][0] == 0 && f[v][1] == 0)
			{
				check = false;
				break;
			}
			vec[u].push_back({v,f[v][0],f[v][1]});
		}
	}
	if(deg == 0)
	{
		f[u][1] = 0;
		f[u][0] = 1;
	}
	else
	{
		sort(vec[u].begin(),vec[u].end(),cmp1);
		tdx[u] = -1;
		for(int i = 0;i < vec[u].size();i++)
		{
			if(vec[u][i].ck1 == 1 && vec[u][i].ck0 == 0)
			{
				tdx[u] = i;
			}
			else 
			{
				break;
			}
		}
		bool mody = false;
		if(tdx[u]+1 < vec[u].size() && vec[u][tdx[u]+1].ck1 == 1 &&  vec[u][tdx[u]+1].ck1 == 0)
		{
			mody = true;
		}
		if((deg[u]-(tdx[u]+1))%2 == 0)
		{
			f[u][0] = 1;
			if(mody)
				f[u][1] = 1;
		}
		else
		{
			f[u][1] = 1;
			if(mody)
				f[u][0] = 1;
		}
	}
	return check;
}

void efs(int u,int st)
{
	int i = 0;
	for(;i <= tdx[u];i++)
	{
		efs(vec[u][i].idx,1);
	}
	if(st == 0)
	{
		if((deg[u]-(tdx[u]+1))%2 != 0)
		{
			efs(vec[u][i].idx,1);
			i++;
		}
	}
	else
	{
		if((deg[u]-(tdx[u]+1))%2 != 1)
		{
			efs(vec[u][i].idx,1);
			i++;
		}
	}
	output.push_back(u);
	for(;i < vec[u].size();i++)
	{
		efs(vec[u][i].idx,0);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	for(int i = 1;i <= n;i++)
	{
		int u;
		cin >> u;
		if(u != 0)
		{
			adde(u,i);
			adde(i,u);
		}
	}
	bool res = dfs(1,0);
	if(res == 0 || f[1][0] == 0)
	{
		cout << "NO\n";
		return 0;
	}
	cout << "YES\n";
	efs(1,0);
	for(int i = 0;i < output.size();i++)
	{
		cout << output[i] << "\n";
	}
	return 0;
}

到了这里,关于CF963B Destruction of a Tree 题解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CF1011A Stages 题解

    题目意思: 给你一个长度为 n n n 的字符串 a a a ,在这个字符串中选一个长度为 k k k 的好串(好串标准是啥自己去题目里看吧),问这个好串的最小价值是多少。 思路: 贪心。 首先我们将字符串 a a a 里面的字符进行排序。 因为要最小的价值,所以排好序后的 a a a 的第一个

    2024年02月12日
    浏览(31)
  • 【学习笔记】CF1783G Weighed Tree Radius

    如果 w v ( u ) w_v(u) w v ​ ( u ) 指代的就是直径,或者说我们再添一项 a v a_v a v ​ ,那么我们几乎就做完了。 于是自然而然想到换一个定义: d ( u , v ) = dist ( u , v ) + a u + a v d(u,v)=text{dist}(u,v)+a_u+a_v d ( u , v ) = dist ( u , v ) + a u ​ + a v ​ 。 发现这样转化过后,设直径的两个端点

    2024年02月16日
    浏览(35)
  • CF1145G AI Takeover 题解

    人工智能取得了进展。在这一题中,我们考虑的是石头剪刀布游戏。 然而,比赛的前一天晚上有一群人把机器人弄坏了,于是使用一个程序替代。 您需要找到一个策略,使您能够获胜。祝你好运! 为了方便,石头剪刀布分别用三个字符表示: R , P , S 。 本题有 6 个测试点,

    2024年03月26日
    浏览(44)
  • CF338D GCD Table 题解

    你有一个长度为 (k) 的数列 (a) , 询问是否存在 (xin[1,n]~~~yin[1,m]) 使得 (forall i~~~ gcd(x,y+i-1)=a_i) 。 我们转换一下可以得到: [forall i ~~left{ begin{matrix}xequiv 0pmod{a_i} \\\\y+i-1equiv 0pmod{a_i}end{matrix}right.] 前面一个 (x) 很好解决,直接 最大公倍数 。 (y) 可以转化一下:

    2024年02月07日
    浏览(38)
  • CF1120 D. Power Tree 巧妙的图论转化

    传送门 [前题提要]:无 题目描述: 考虑对一个点的子树的所有 叶子节点 进行增减任意值.不难联想到对一个点的子树的 所有节点 增减任意值的做法.所以考虑使用类似于树链剖分的方式将树上修改化为链上区间修改. 考虑记录一个点的所有叶子节点,并且按照 d f s dfs df s 序将其

    2024年02月10日
    浏览(39)
  • 洛谷 P8742题解

    简单版(P2347)传送门 原题传送门 有一道 类似 的题目(P2347),先扯一扯~ 动态规划入门题(01背包 可行性问题 )~ 我们 设 (dp_j) 为能否用砝码称出 (j) 重量 ,1 为 可以 ,0 为 不可以 。 为了转移, (dp_{_{0}} gets 1) , 什么都不放时,重量为 0 ,因此可以称出。 那么 枚举

    2024年02月06日
    浏览(55)
  • 洛谷P1249题解

    一个正整数一般可以分为几个互不相同的自然数的和,如 3 = 1 + 2 3=1+2 3 = 1 + 2 , 4 = 1 + 3 4=1+3 4 = 1 + 3 , 5 = 1 + 4 = 2 + 3 5=1+4=2+3 5 = 1 + 4 = 2 + 3 , 6 = 1 + 5 = 2 + 4 6=1+5=2+4 6 = 1 + 5 = 2 + 4 。 现在你的任务是将指定的正整数 n n n 分解成若干个互不相同的自然数的和,且使这些自

    2024年02月05日
    浏览(52)
  • 洛谷AT4888 题解-伦伦数

    A positive integer XX is said to be a lunlun number if and only if the following condition is satisfied: In the base ten representation of XX (without leading zeros), for every pair of two adjacent digits, the absolute difference of those digits is at most 11 . For example, 12341234 , 11 , and 334334 are lunlun numbers, while none of 3141531415 

    2024年02月06日
    浏览(52)
  • CF1178F1 Short Colorful Strip 题解

    题目描述 这是F题的第一个子任务。F1和F2的区别仅在对于m和时间的限制上 有n+1种颜色标号从0到n,我们有一条全部染成颜色0的长为m的纸带。 Alice拿着刷子通过以下的过程来给纸带染色: 我们按照从1到n的顺序进行染色,进行每次染色时,我们选取一个区间[ai,bi],0=aibi=m,并

    2024年02月01日
    浏览(38)
  • 洛谷 P1336 最佳课题选择 题解

    题目链接 状态:考虑 (f_{i,j}) 表示前 (i) 种论文里面,一共写了 (j) 篇,的最少花费时间。 转移策略:我们一次考虑每一种论文写多少篇。假设写 (k) 篇, (k in [0,j] cap mathbb{Z}) ,有转移方程: [f_{i,j} = min(f_{i-1,j-k} + text{cost}(i,k)), k in [0,j] cap mathbb{Z}] 其中 [text{

    2024年02月14日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包