1. 程式人生 > >Codeforces-964D Destruction of a Tree(貪心)

Codeforces-964D Destruction of a Tree(貪心)

stream AI urn const return || air 所有 mat

題意:給你一顆節點數目為n的樹,問你能否每次刪除一個度為偶數的節點,同時與該節點相連的路也被刪除,能否在多次刪除操作後刪除掉整棵樹

題解:從根開始dfs處理出每個節點到根的距離。然後貪心的刪除離根最遠的偶數度節點。如何證明這個結論是正確的呢?(補題目的時候是多畫圖然後猜的結論,因為WA了兩發後以為是錯誤的,然後請教了別人,並且證明了這個結論的正確性)因為離根最遠的偶數度節點(其子孫一定都是奇數度數的),在將其刪除後它所在的那顆樹一定被分成兩個奇數節點數(註意是節點數!因為只有奇數樹才能進行刪除操作)的樹,從而它的子孫也可以開始刪除操作,所以從該點開始刪除一定是最優解,如果在當前情況下仍然無法刪除所有點,則輸出NO。

寫的很撮的代碼,去看別人的代碼,發現他們寫的都比我好

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cstring>
#include <iomanip>
#include <set>
#include<ctime>
//CLOCKS_PER_SEC
#define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=4e5+5
; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; int head[N],nx[N],to[N]; int tot=1; struct node { int le,du,num; friend bool operator < (node a, node b){ if(a.le==b.le) { return a.du>b.du; } return a.le>b.le; } }L[N]; void add(int u,int v){ to[tot]=v; nx[tot]=head[u]; head[u]=tot++; } int dfs(int x,int pre){ for(int i=head[x];i;i=nx[i]){ int v=to[i]; if(v==pre)continue; if(v!=pre)L[x].le+=dfs(v,x); } return L[x].le; } bool vis[N]; vector<int>ans; int main(){ fio; int n; cin>>n; int S=-1; for(int i=1;i<=n;i++){ int x; cin>>x; if(x==0){ S=i; continue; } add(i,x); add(x,i); L[i].du++,L[x].du++; L[i].le=1; L[i].num=i; } if(n%2==0)return cout<<"NO\n",0; L[S].le=1; L[S].num=S; dfs(S,S); priority_queue<node>q; for(int i=1;i<=n;i++){ if(L[i].du%2==0) q.push(L[i]); } while(!q.empty()){ node x=q.top(); q.pop(); if(vis[x.num]||L[x.num].du%2==1)continue; vis[x.num]=1; ans.pb(x.num); for(int i=head[x.num];i;i=nx[i]){ int v=to[i]; if(L[v].du)L[v].du--; if(L[v].du==0&&vis[v]==0){ vis[v]=1; ans.pb(v); } else if(L[v].du%2==0&&!vis[v]){ q.push(L[v]); } } } if(ans.size()==n){ cout<<"YES"<<endl; for(auto i:ans){ cout<<i<<endl; } } else cout<<"NO"<<endl; return 0; }

Codeforces-964D Destruction of a Tree(貪心)