题干:
题目描述 Description
给出一棵树,求出树的中心。
为了定义树的中心,首先给每个结点进行标号。对于一个结点K,如果把K从树中删除(连同与它相连的边一起),剩下的被分成了很多块,每一块显然又是一棵树(即剩下的部分构成了一个森林)。则给结点K所标的号就是森林中结点个数最多的树所拥有的结点数。如果结点K的标号不大于其他任何一个结点的标号,则结点K被称为是树的中心。
输入描述 Input Description
输入:
输入的第一行包含一个整数N(1≤N≤16 000),表示树中的结点数。接下来N-1行,每个两个整数a,b,由一个空格分隔,表示a与b之间有一条边。
输出描述 Output Description
输出:
输出两行,第一行两个整数v,T,v表示树的中心结点的标号,T表示树有多少个中心。第二行包含T个数,为所有树的中心的编号,按升序排列。
样例输入 Sample Input
样例输入:
7
1 2
2 3
2 4
1 5
5 6
6 7
样例输出 Sample Output
样例输出:
3 1
1
数据范围及提示 Data Size & Hint
数据范围: 20% N<=100 100% N<=16 000
解题报告:
裸题模板不解释了。。。注意输出的时候有空格、、、他这个样例体现不出来、、开了个num数组记录
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
vector<int> vv[MAX];
int dp[MAX],sum[MAX];
int n;
int dfs(int cur,int root) {
int up = vv[cur].size();
int res = 1,tmp;
//if(up == 1) return 1;
for(int i = 0; i<up; i++) {
int v = vv[cur][i];
if(v == root) continue;
tmp = dfs(v,cur);
dp[cur] = max(dp[cur],tmp);
res += tmp;
}
dp[cur] = max(dp[cur],n-res);
return sum[cur] = res;
}
int main()
{
while(~scanf("%d",&n)) {
for(int i = 1; i<=n; i++) vv[i].clear(),dp[i]=1;
for(int i = 1; i<=n-1; i++) {
int x,y;
scanf("%d%d",&x,&y);
vv[x].pb(y);
vv[y].pb(x);
}
dfs(1,-1);
int minn = 0x3f3f3f3f;
for(int i = 1; i<=n; i++) {
minn = min(minn,dp[i]);
}
int cnt = 0,flag = 0;
for(int i = 1; i<=n; i++) {
if(dp[i] == minn ) cnt++;
}
printf("%d %d\n",minn ,cnt);
for(int i = 1; i<=n; i++) {
if(dp[i] == minn ) {
if(flag != 0) putchar(' ');
flag=1;
printf("%d",i);
}
}
printf("\n");
}
return 0 ;
}