1. 程式人生 > >Codeforces 963B Destruction of a Tree 【貪心】

Codeforces 963B Destruction of a Tree 【貪心】

UC nbsp span include end 準備 cto stream 父親節

本題的貪心策略是:每次刪除連到葉子結點的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 }

Codeforces 963B Destruction of a Tree 【貪心】