您的位置:首页 > 其它

SGU 134 Centroid

2011-09-05 13:21 253 查看
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

/*这个题出题很容易,但是提交的时候需要注意很多
  第一次所有的数都用int型提交了,树据只过了三组,卡在第四组上了,前三组还是比较弱的
  因为用的vc6.0 对long long类型编译不通过,所以直接改成了__int64类型,两次编译错误,
  后来改成long long了,在别的编译器上编译
  但初始最大值的时候数值太大,本地编译不能通过,改小了之后提交还是wa,最后将最大值改
  成了19位的,虽然本地编译不通过,但是提交后总算AC了。
  题目的意思是:定义了树的形心,也就是将树中的任意某点k去掉后,分成的各部分中节点数最大的那个值作为
  k的一个权值,然后整个树中权值最小的那个点或者几个点就是这里的形心。
  */
const long long MAXX=16010;

long long dp[MAXX];//dp[i]以i为根的子树总共包含的节点数。
bool vis[MAXX];
vector<long long> tree[MAXX];//存树的逻辑结构
long long num[MAXX];//存符合条件的所有点
long long pt,n;

long long max(long long a,long long b)
{
	return a>b?a:b;
}

void DFS(long long root)
{
	long long v;
	vis[root]=true;
	dp[root]=1;
	for(long long i=0;i<tree[root].size();i++){
		v=tree[root][i];
		if(vis[v])continue;
		DFS(v);
		dp[root]+=dp[v];
	}
}

void DP(long long root,long long pre)
{
	long long v,temp=n-dp[root];
	for(long long i=0;i<tree[root].size();i++){
		v=tree[root][i];
		if(v==pre)continue;
		temp=max(temp,dp[v]);
		DP(v,root);
	}
	dp[root]=temp;
}

int main()
{
	long long x,y,i;
	scanf("%lld",&n);
	long long min;
	pt=0;
	memset(dp,0,sizeof(dp));
	for(i=1;i<n;i++)
	{
		scanf("%lld%lld",&x,&y);
		tree[x].push_back(y);
		tree[y].push_back(x);
	}
	memset(vis,false,sizeof(vis));
	DFS(1);
	DP(1,-1);
	min=90000000000000000;
    for(i=1;i<=n;i++){
		if(dp[i]<min){
			min=dp[i];
			pt=0;
			num[pt++]=i;
		}else if(dp[i]==min){
			num[pt++]=i;
		}
	}
	printf("%lld %lld\n",dp[num[0]],pt);
	for(i=0;i<pt;i++){
		printf("%lld\n",num[i]);
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: