1. 程式人生 > >【CodeVS - 3639】(樹的重心模板,裸題)

【CodeVS - 3639】(樹的重心模板,裸題)

題幹:

題目描述 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 ;
 }