codeforces 964D

Destruction of a Tree

题意:给一个n个节点的树, 每次可以删除度为偶数的节点,并把与之相连的边删除,问是否可以把所有节点删除

思路:有一个结论,偶数节点的树一定不可以全部删除, 证明:首先,删除一个点一定删除偶数条边,一个偶数节点的树肯定不能一次把所有边删除,因为偶数点的树有奇数条边,那么删除一个点以后同时删除偶数条边的结果是:得到了偶数颗树,并且这些树的节点数之和为奇数,也就是说必然有一颗树的大小还是偶数,也就是说明,一颗大小为偶数的树无论怎么删都会留下大小为偶数的子树,由前面推得的结论可知,偶数节点的树一定不可以全部删除。那么只需要dfs判断每个节点可不可以删除即可,一个节点是否可以删除取决于它的子树的大小是否全为奇数,同时如果一个节点删除了,那么必然影响到它孩子的度树,所以在删除完一个节点以后要堆它的孩子继续dfs

AC代码:

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+9;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=2e5+100;

int n, fu, p[N], du[N], vis[N*2], as[N], siz[N];
int head[N*2], to[N*2], nex[N*2], tot=1;

void add(int u, int v) {
    to[tot] = v;
    nex[tot] = head[u];
    head[u] = tot++;
}
vector<int> ans;

void dfs0(int u, int fa) {
    siz[u] = 1;
    for(int i=head[u]; i!=-1; i=nex[i]) {
        int v = to[i];
        if(v == fa) continue;
        dfs0(v, u);
        siz[u] += siz[v];
    }
}

void dfs(int u,  int fa) {
    if(ans.size() >= n || as[u]) return;
    if(du[u]%2 == 0) {
        int sz=0;
        for(int i=head[u]; i!=-1; i=nex[i]) {
            int v = to[i];
            if(as[v]) continue;
            if(v == p[u]) sz = n-siz[u];
            else sz = siz[v];
            if(sz%2 == 0) return;
        }
        as[u] = 1, ans.pb(u);
        for(int i=head[u]; i!=-1; i=nex[i]) {
            int v = to[i];
            if(v == fa) continue;
            du[v]--;
            dfs(v, u);
        }
    }
}

int main() {
    scanf("%d", &n);
    mem(head, -1);
    for(int i=1; i<=n; ++i) {
        scanf("%d", &p[i]);
        if(p[i] != 0) {
            add(i, p[i]), add(p[i], i);
            du[i]++, du[p[i]]++;
        }
        else fu = i;
    }
    dfs0(fu, 0);
    for(int i=1; i<=n; ++i) {
        if(du[i]%2==0) dfs(i, 0);
        if(ans.size() >= n) break;
    }
    for(int i=1; i<=n ; ++i) {
        if(!as[i]) return 0*printf("NO");
    }
    printf("YES\n");
    for(auto i : ans) printf("%d\n", i);
    return 0;
}

 

posted on 2018-04-18 22:07  lazzzy  阅读(174)  评论(0编辑  收藏  举报

导航