题目链接:Destruction of a Tree
题意
给定一个 n n 个节点的树,每次可以从树上选择一个度为偶数的节点进行删除,每删除一个节点,与这个节点相连的所有边都被删除,问能否删除整棵树。
输入
第一行为一个整数 ,第二行为 n n 个整数 ,如果 pi≠0 p i ≠ 0 ,表示节点 pi p i 和 i i 之间有一条连边,数据保证给定的结构是一棵树。
输出
如果无法删除整棵树,输出 ,否则在第一行输出 YES Y E S ,接下去 n n 行输出 个整数,表示删除节点的顺序。
样例
输入 |
---|
5 0 1 2 1 2 |
输出 |
YES 1 2 3 5 4 |
提示 |
删点过程如下: |
输入 |
---|
4 0 1 2 3 |
输出 |
NO |
题解
从叶子节点往树根 dfs d f s ,只要发现某个节点的度为偶数,就立即删除这个节点并往下 dfs d f s ,最后注意剪枝。
过题代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <functional>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 200000 + 100;
int n, p, cnt;
int ans[maxn], deg[maxn];
bool vis[maxn];
vector<int> G[maxn];
queue<int> que;
void dfs(int f, int x, bool flag) {
int len = G[x].size();
if(!flag) {
for(int i = 0; i < len; ++i) {
int pos = G[x][i];
if(!vis[pos] && pos != f) {
dfs(x, pos, false);
}
}
}
if(deg[x] % 2 == 0) {
deg[x] = 0;
ans[cnt++] = x;
vis[x] = true;
for(int i = 0; i < len; ++i) {
int pos = G[x][i];
if(!vis[pos]) {
--deg[pos];
if(pos != f) {
dfs(x, pos, true);
}
}
}
}
}
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
#endif // LOCAL
while(scanf("%d", &n) != EOF) {
cnt = 0;
for(int i = 1; i <= n; ++i) {
G[i].clear();
deg[i] = 0;
vis[i] = false;
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &p);
if(p != 0) {
G[i].push_back(p);
G[p].push_back(i);
++deg[i];
++deg[p];
}
}
dfs(1, 1, false);
if(cnt != n) {
printf("NO\n");
continue;
}
printf("YES\n");
for(int i = 0; i < cnt; ++i) {
printf("%d\n", ans[i]);
}
}
return 0;
}