CF963B Destruction of a Tree
题目大意
给你一棵树,如果树上的节点有偶数条边与它相连,则这个节点是可删除的,删除这个节点后所有与之相连的边也将删除。
判断一棵树是否可以依次删除所有节点。
可以删除输出 YES
,并输出依次删除的点的编号; 不可以则输出 NO
。
解题思路
显然,叶子节点度数为 ,必须要先删除父亲节点,如果父亲节点是偶数那直接删,但是如果是奇数还得继续往上找。
也就是说,我们可以先从下往上搜一遍树,看到度数为偶数的点直接删除,加入答案。
剩下的再从上到下扫一遍,如果有奇数度节点,那么肯定他的儿子与父亲都不是偶数度节点,无法删除,输出 NO
,否则就直接删除这个节点。
CODE
#include <bits/stdc++.h>
#define _ 200005
using namespace std;
inline int read()
{
int x = 0;
char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
{
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x;
}
int n, fa[_], deg[_], vis[_], head[_], tot;
stack<int> sta;
int ans[_], num;
struct edge
{
int to, next;
} e[_ << 1];
inline void add(int u, int v)
{
e[++tot] = {v, head[u]};
head[u] = tot;
}
void dfs1(int x, int f)
{
fa[x] = f;
sta.push(x);
for (int i = head[x]; i; i = e[i].next)
{
int v = e[i].to;
if (v == f)
continue;
dfs1(v, x);
}
}
void dfs2(int x)
{
vis[x] = 1;
ans[++num] = x;
for (int i = head[x]; i; i = e[i].next)
{
int v = e[i].to;
deg[v]--;
if (v == fa[x] || vis[v])
continue;
if (!(deg[v] & 1))
dfs2(v);
}
}
signed main()
{
n = read();
int v;
for (int i = 1; i <= n; i++)
{
v = read();
if (v)
{
add(i, v);
add(v, i);
++deg[v];
++deg[i];
}
}
dfs1(1, -1);
while (!sta.empty())
{
int az = sta.top();
sta.pop();
if (!(deg[az] & 1))
dfs2(az);
}
if (num == n)
{
puts("YES");
for (int i = 1; i <= num; i++)
printf("%d\n", ans[i]);
}
else
puts("NO");
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122080
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下