天天看點

樹形DP______Tree Cutting( POJ 2378 )

Description

After Farmer John realized that Bessie had installed a "tree-shaped" network among his N (1 <= N <= 10,000) barns at an incredible cost, he sued Bessie to mitigate his losses. 

Bessie, feeling vindictive, decided to sabotage Farmer John's network by cutting power to one of the barns (thereby disrupting all the connections involving that barn). When Bessie does this, it breaks the network into smaller pieces, each of which retains full connectivity within itself. In order to be as disruptive as possible, Bessie wants to make sure that each of these pieces connects together no more than half the barns on FJ. 

Please help Bessie determine all of the barns that would be suitable to disconnect.

Input

* Line 1: A single integer, N. The barns are numbered 1..N. 

* Lines 2..N: Each line contains two integers X and Y and represents a connection between barns X and Y.

Output

* Lines 1..?: Each line contains a single integer, the number (from 1..N) of a barn whose removal splits the network into pieces each having at most half the original number of barns. Output the barns in increasing numerical order. If there are no suitable barns, the output should be a single line containing the word "NONE".

Sample Input

10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8      

Sample Output

3
8      

題意:

給一顆n個結點的樹,節點編号為1~n,問删除一個節點之後,讓剩下的分支中節點數量最多的盡量少。

   可能有多種方案,按編号順序輸出。

分析:

對于i節點去掉之後會産生其子樹,和整個樹去掉i為根節點的樹。先統計出所有節點為根節點的子樹節點數,然後走一發dp即可求出來。

代碼:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
using namespace std;
int to[100010],ft[50010],nt[100010],tot;
int num[50010];
int book[50010];
int n,u,v;
void addedge(int u,int v)
{
    to[tot] = v;
    nt[tot] = ft[u];
    ft[u] = tot ++;
}
int dfs(int x,int pre)
{
    num[x] = 1;
    int Max = 0;
    for(int i = ft[x] ; i != -1 ; i = nt[i])
    {
        int y = to[i];
        if(y == pre)continue;
        int step = dfs(y,x);
        num[x] += step;
        Max = max(Max,step);
    }
    Max = max(Max,n - num[x]);
    book[x] = Max;
    return num[x];
}

int main()
{
    memset(ft,-1,sizeof(ft));
    scanf("%d",&n);
    for(int i = 1 ; i < n ; i ++)
    {
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    dfs(1,0);
    bool k = 0;
    int Min = 0x3f3f3f3f;
    for(int i = 1 ; i <= n ; i ++)
        Min = min(Min,book[i]);
    for(int i = 1 ; i <= n ; i ++)
        if(book[i] == Min)
    {
        if(k == 0)printf("%d",i),k = 1;
        else printf(" %d",i);
    }
    printf("\n");
    return 0;
}