POJ.2378 Tree Cutting (树形DP 树的重心)

来源:互联网 发布:lol西西软件下载 编辑:程序博客网 时间:2024/05/21 14:02

POJ.2378 Tree Cutting (树形DP 树的重心)

标签(空格分隔): 动态规划


题意分析

有一棵树,是否能找到一个节点,删除后保证最大联通块的节点个数不超过总结点数的一半。若有则一次输出满足的节点编号,否则输出NONE。

和树的重心很相似,回顾一下什么是树的重心,树的重心是指,删除个节点以后,最大联通块的节点数最少。
对于每个节点,都能求解出来,在删除他以后其所形成的所有联通块中的节点最多的个数,保存在DP数组中,最后我们依次遍历数组,当dp[i]2n时,输出即可。

代码总览

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define nmax 20010using namespace std;struct edge{    int to,next;}edg[nmax*2];int head[nmax],sz[nmax];int dp[nmax];int tot = 0;int t,n;void add(int u, int v){    edg[tot].to = v;    edg[tot].next = head[u];    head[u] = tot++;}void dfs(int rt, int fa){    sz[rt] = 1;    dp[rt] = 0;    int tmp = 0,tmpson = 0;    for(int i = head[rt]; i!=-1 ;i = edg[i].next){        int nxt = edg[i].to;        if(nxt != fa){            dfs(nxt,rt);            sz[rt]+=sz[nxt];            if(sz[nxt] > tmp){                tmp = sz[nxt];                dp[rt] = tmp;            }        }    }    if(tmp < n-sz[rt])        dp[rt] = tmp = n-sz[rt];}void init(){    memset(head,-1,sizeof head);    tot = 0;}int main(){    //freopen("im.txt","r",stdin);    scanf("%d",&n);    init();    for(int i = 0;i<n-1;++i){        int x,y;        scanf("%d %d",&x,&y);        add(x,y);        add(y,x);    }    dfs(1,0);    bool isoutput = false;    for(int i = 1;i<=n;++i){        if(dp[i] * 2 <=n ){            printf("%d\n",i);            isoutput = true;        }    }    if(!isoutput) printf("NONE\n");    return 0;}
原创粉丝点击