#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-04-15 11:37:23 发布