CF963B Destruction of a Tree
阿新 • • 發佈:2021-11-28
題目大意
給你一棵樹,如果樹上的節點有偶數條邊與它相連,則這個節點是可刪除的,刪除這個節點後所有與之相連的邊也將刪除。
判斷一棵樹是否可以依次刪除所有節點。
可以刪除輸出 YES
,並輸出依次刪除的點的編號; 不可以則輸出 NO
。
解題思路
顯然,葉子節點度數為 \(1\),必須要先刪除父親節點,如果父親節點是偶數那直接刪,但是如果是奇數還得繼續往上找。
也就是說,我們可以先從下往上搜一遍樹,看到度數為偶數的點直接刪除,加入答案。
剩下的再從上到下掃一遍,如果有奇數度節點,那麼肯定他的兒子與父親都不是偶數度節點,無法刪除,輸出 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/15614725.html