#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;
}
SGU 134 Centroid
最新推荐文章于 2016-08-01 15:33:51 发布
