来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

小G想要把自己家院子里的橘子树搬到家门口(QAQ。。就当小G是大力水手吧)
可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点。 怎么描述这棵树呢。。。就把它看成由一个个节点构成的树吧。结点数就
代表树重。

输入描述:

多组数据输入输出, 第一行包含一个整数n(3<=n<=1000)代表树的结点的个数 以下n-1行描述(1-n)节点间的连接关系。 输出描述:
输出两个个整数 x,num 分别代表树的平衡点,和删除平衡点后最大子树的结点数(如果结点数相同输出编号小的)。

示例1
输入
复制

3
1 2
1 3

输出
复制

1 1

题解:

树型dp入门
状态转移方程:dp[i]=max(n-tot[i],max(tot[k]))
dp[x]:表示以x为根的树的节点数
在dfs过程中把状态转移方程带进去

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
vector<int>edge[maxn];
int num,ans;
int dp[maxn];
int n;
void dfs(int u,int fa)
{
    dp[u]=1;
    int maxx=0;
    for(int i=0;i<edge[u].size();i++)
    {
        int v=edge[u][i];
        if(v==fa)continue;
        dfs(v,u);
        dp[u]+=dp[v];//v是u的子树 
        maxx=max(dp[v],maxx);
    }
    maxx=max(maxx,n-dp[u]);//判断是这个子树重,还是另一个 
    // dp[i]=max(n-tot[i],max(tot[k])) 树形dp 
    if(maxx<num)//删除平衡点后最大子树的结点数
    {
        num=maxx;
        ans=u; 
    }
    else if(maxx==num)
    {
        if(ans>u)ans=u;//如果结点数相同,我们要编号更小的 
     } 
}
int main()
{

    while(cin>>n)
    {
        num=ans=0x7f;
        for(int i=1;i<=n;i++)
        {
            edge[i].clear();
            dp[i]=0;
        }
        for(int i=1;i<n;i++)
        {
            int u,v;
            cin>>u>>v;
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        dfs(1,0);
        cout<<ans<<" "<<num<<endl;
    }
}