Codeforces 963B Destruction of a Tree 【贪心】

本题的贪心策略是:每次删除连到叶子结点的dfs链上离根最远的偶数度的结点

greed is good

实现方法是先维护一个degree[i]表示第i个点有多少个度,然后dfs,当每一个结点的所有子节点被访问后准备返回时判断当前结点degree的奇偶性,如果是偶数就删除,是奇数就什么都不做。这样能保证你删除的结点【的子孙】度数都是奇数,及保证删除了【离根最远的偶数度的结点】。每次删除要把它父亲和son的degree都减1,并且如果son的degree减完以后是偶数的话就把son也删除。(以为这样能保证该son是这条链上离root的最远节点,及该son的子孙度数都一定是奇数)注意如果parent的degree减完是偶数的话我们不能删掉parent,因为parent的所有子结点没有访问完,我们无法确定parent是不是离根最远的偶数度结点。

 1 #include<iostream>
 2 #include<vector>
 3 #define MAXN 200000
 4 using namespace std;
 5 
 6 int n;
 7 int ans[MAXN+5],root,vis[MAXN+5],del[MAXN+5];
 8 int degree[MAXN+5],parent[MAXN+5];//第i个节点有多少度 ,每个节点的parent 
 9 vector<int> edge[MAXN+5];
10 int top;
11 //从下往上删偶数度的点 
12 
13 void Del(int node){//删除node点,并且递归删除新的可删除的点 
14     ans[++top]=node;
15     del[node]=1;//把当前node删掉 
16     for(int i=0;i<edge[node].size();i++){
17         int v=edge[node][i];
18         if( del[v] ) continue;
19         degree[v]-=1;//一个结点被删除后只会影响他 parent和son的degree 
20         if(degree[v]%2==0 && parent[node]!=v) Del(v);//不能删他的父亲结点,因为不知道父亲节点是不是离根最远的偶数度结点;
21                                                         //但如果是son的话可以保证,因为该节点后代的度数都是基数 
22     }
23 }
24 
25 void dfs(int node){
26     vis[node]=1;
27     
28     for(int i=0;i<edge[node].size();i++){ 
29         int v=edge[node][i];
30         if(vis[v]) continue; 
31         parent[v]=node;
32         dfs(v);
33     }
34 
35     if(degree[node]%2==0) Del(node); //如果偶数度那删掉
36         
37 }
38 
39 int main(){
40 
41 cin>>n;
42 for(int i=1;i<=n;i++) {
43     int v; cin>>v;
44     if(v==0) root=i;
45     else{
46         edge[i].push_back(v);
47         edge[v].push_back(i);
48     }
49 }
50 
51 for(int i=1;i<=n;i++) degree[i]=edge[i].size();
52 dfs(root);
53 
54 if( top==n ){
55     cout<<"YES"<<endl;
56     for(int i=1;i<=n;i++) cout<<ans[i]<<endl;
57 }
58 else cout<<"NO";
59 
60     
61     
62     return 0;
63 }

猜你喜欢

转载自www.cnblogs.com/ZhenghangHu/p/8973587.html