【USACO 2004 DEC】网络破坏Tree Cutting(DFS)

题目描述

约翰意识到贝茜建设网络花费了他巨额的经费,就把她解雇了.贝茜很愤怒,打算狠狠报

复.她打算破坏刚建成的约翰的网络.

约翰的网络是树形的,连接着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 }

 

posted @ 2018-07-29 14:46  gzh01  阅读(348)  评论(0编辑  收藏  举报