Codeforces 963B Destruction of a Tree 【貪心】
阿新 • • 發佈:2018-04-30
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(intnode){//刪除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 【貪心】