【CodeVS - 3639】(樹的重心模板,裸題)
阿新 • • 發佈:2018-11-22
題幹:
題目描述 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 ; }