1. 程式人生 > 其它 >CF963B Destruction of a Tree

CF963B Destruction of a Tree

題目大意

給你一棵樹,如果樹上的節點有偶數條邊與它相連,則這個節點是可刪除的,刪除這個節點後所有與之相連的邊也將刪除。

判斷一棵樹是否可以依次刪除所有節點。

可以刪除輸出 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