poj 1655 Balancing Act(树形DP)

来源:互联网 发布:老司机开车 知乎 编辑:程序博客网 时间:2024/04/30 15:54

题意:求树上的一个点,删除该点后形成的众多树中,最大的树的大小最小。换句话说就是求树的重心。

思路:DP+DFS

定义状态:dp[a]表示 以a 为根节点的子树大小

然后一遍DPS,每次判断a的子树的各个dp值和n-dp[a]的值中的最大值,答案存最小的那个即可。因为存的是无向图,忘记边数乘2了,WA了两次。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define inf 0x3f3f3f3fusing namespace std;const int maxn=22222;int dp[maxn];struct node{    int to;    int next;};node edge[maxn<<1];int vis[maxn];int head[maxn];int ans;int nore;int n;int edge_sz;void init(){    memset(head,-1,sizeof(head));    edge_sz=0;    ans=inf;    nore=1;}void addedge(int a,int b){    edge[edge_sz].to=b;    edge[edge_sz].next=head[a];    head[a]=edge_sz++;}void cal(int u,int p)//求重心{    dp[u]=1;    int v;    int mx=0;    for(int i=head[u];i!=-1;i=edge[i].next)    {        v=edge[i].to;        if(v!=p)        {            cal(v,u);            dp[u]+=dp[v];            mx=max(mx,dp[v]);        }    }    mx=max(mx,n-dp[u]);    if(mx==ans)    {        if(u<nore)        {            nore=u;        }    }    if(mx<ans)    {        ans=mx;        nore=u;    }}void input(){    scanf("%d",&n);    for(int i=0;i<n-1;i++)    {        int a,b;        scanf("%d%d",&a,&b);        addedge(a,b);        addedge(b,a);    }}int main(){   // freopen("in.txt","r",stdin);    int t;    scanf("%d",&t);    while(t--)    {        init();        input();        cal(1,0);        printf("%d %d\n",nore,ans);    }    return 0;}