codeforces 964D 思维,dfs

D. Destruction of a Tree

题意:
一棵树,每次可选择一个度为偶数的点删掉,并且这个点连的边也删掉,问最后能否把所有点删掉。
tags:
注意到一个点:要把一棵树全部删掉,那它的点数一定是奇数。因为每次是删掉偶数条边,只有所有的边数是偶数时才能全部删掉。
所以在 dfs 的时候,如果一个子树的 Size 是偶数,那就要先删掉这棵子树才能删 root 点。

// 964D
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005;

int n, deg[N], sz[N];
vector< int > G[N];
void dfs_sz(int u, int fa) {
    ++sz[u];
    for(int to : G[u]) if(to!=fa) {
        dfs_sz(to, u);
        sz[u] += sz[to];
    }
}
vector< int > ans;
bool dfs(int u, int fa) {
    for(int to : G[u])
        if(to!=fa && !(sz[to]&1))
        {
            if(!dfs(to, u)) return false;
            --deg[u];
        }
    if(deg[u]&1) return false;
    ans.PB(u);
    for(int to : G[u])
        if(to!=fa && (sz[to]&1))
        {
            --deg[to];
            if(!dfs(to, u)) return false;
        }
    return true;
}
int main()
{
    scanf("%d", &n);
    int pi;
    rep(i,1,n) {
        scanf("%d", &pi);
        if(pi!=0) {
            G[i].PB(pi), G[pi].PB(i);
            ++deg[i], ++deg[pi];
        }
    }
    dfs_sz(1, -1);
    if(dfs(1,-1)) {
        puts("YES");
        for(int v : ans) printf("%d
", v);
    }
    else puts("NO");

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/8884918.html