来源:牛客网

时间限制: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;
	}
}