POJ - 2378 Tree Cutting(树形dp)

d.n个节点的树,删除一个点,得到的最大联通分支大小不大于总节点数的一半,求这样点的集合

s.树形dp

c.网上找的一个,看着头文件啥的可以参考,先贴在着,抽空自己写写

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define N 10010
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
int dp[N],n,num[N],used[N];//dp[i]表示去掉i节点后所有联通分支中的最大的节点数
//num[i]表示以i为根节点的子树的总节点数
vector<int>e[N];

int dfs(int root)
{
    num[root]=1;
    used[root]=1;
    for(int i=0; i<e[root].size(); ++i)
    {
        int son=e[root][i];
        if(used[son])continue;
        num[root]+=dfs(son);//num[root]表示以root为根节点的子树的总节点数
        dp[root]=max(dp[root],num[son]);//root下面的联通分支的最大值
    }
    dp[root]=max(dp[root],n-num[root]);//与root上面的联通分支比较,取大的值
    return num[root];
}
int main()
{
    int res[N];
    while(~scanf("%d",&n))
    {
        memset(dp,0,sizeof(dp));
        memset(used,0,sizeof(used));
        for(int i=1; i<=n; ++i)
            e[i].clear();
        int a,b;
        for(int i=0; i<n-1; ++i)
        {
            scanf("%d%d",&a,&b);
            e[a].push_back(b);
            e[b].push_back(a);
        }
        dfs(1);
        int l=0,f=0;
        for(int i=1; i<=n; ++i)
            if(dp[i]<=n/2)
            {
                f=1;
                printf("%d\n",i);
            }
        if(!f)printf("NONE\n");
    }
    return 0;
}
View Code

 

posted @ 2016-03-14 18:23  gongpixin  阅读(232)  评论(0编辑  收藏  举报