1. 程式人生 > >【USACO 2004 DEC】網絡破壞Tree Cutting(DFS)

【USACO 2004 DEC】網絡破壞Tree Cutting(DFS)

pre nbsp \n printf 整數 back push_back sca 如果

題目描述

約翰意識到貝茜建設網絡花費了他巨額的經費,就把她解雇了.貝茜很憤怒,打算狠狠報

復.她打算破壞剛建成的約翰的網絡.

約翰的網絡是樹形的,連接著N(1≤N≤10000)個牛棚.她打算切斷某一個牛棚的電源,使和這個牛棚相連的所有電纜全部中斷.之後,就會存在若幹子網絡.為保證破壞夠大,每一個子網的牛棚數不得超過總牛棚數的一半,哪些牛棚值得破壞呢?

輸入

第1行:一個整數N.

第2到N行:每行輸入兩個整數,表示一條電纜的兩個端點.

輸出

按從小到大的順序,輸出所有值得破壞的牛棚.如果沒有一個值得破壞,就輸出“NONE”.

本題網絡是一個無根樹,那麽我們可以進行搜索,記錄每一棵以x節點為根的子樹的節點數,最後枚舉每一個點,假如這個點以它的子節點為根的子樹節點數,與節點總數減去這個點為根的子樹節點數均不大於n/2,就可以將這個點輸出。(其實這道題根本不可能有NONE的情況)

 1 #include <cstdio>
 2 #include <vector>
 3  
 4 #define N 10001
 5  
 6 int n,a,b,ans,num[N],pre[N];
 7 std::vector<int> g[N];
 8  
 9 int dfs(int u,int fa){
10     pre[u]=fa;
11     if((g[u].size()==1)&&(u!=1))return num[u]=1;
12     int sum=0;
13     for(int i=0
;i<g[u].size();++i){ 14 int v=g[u][i]; 15 if(v==fa)continue; 16 sum+=dfs(v,u); 17 } 18 return num[u]=sum+1; 19 } 20 21 int main(void){ 22 scanf("%d",&n); 23 for(int i=1;i<n;++i){ 24 scanf("%d%d",&a,&b); 25 g[a].push_back(b);
26 g[b].push_back(a); 27 } 28 dfs(1,0); 29 for(int i=1;i<=n;++i){ 30 bool p=true; 31 if(num[1]-num[i]>n/2)continue; 32 for(int j=0;j<g[i].size();++j){ 33 int v=g[i][j]; 34 if(v==pre[i])continue; 35 if(num[v]>n/2)p=false; 36 } 37 if(p){ 38 ++ans; 39 printf("%d\n",i); 40 } 41 } 42 if(ans==0)printf("NONE"); 43 }

【USACO 2004 DEC】網絡破壞Tree Cutting(DFS)