poj 1655 Balancing Act 求树的重心

题目链接:http://poj.org/problem?id=1655

 

题意:

给出一棵树,求树的重心。

树的重心:在树中的一个点,要求将其删去后,结点最多的树的结点个数最小。

 

思路:

首先dfs一遍,转化为有根树,求出每个结点包括自己在内的子节点数sonSum[i]和这个结点下面的子树最多的个数sonMax[i]。

那么删去结点后,剩余的另一部分就是leftSum = N - sonSum[i]。

然后取leftSum和sonMax的较大值,再求所有结点的最小值即可。

 

 1 //#include <bits/stdc++.h>
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <vector>
 5 #include <cstring>
 6 using namespace std;
 7 int T, N;
 8 #define maxn 20010
 9 vector <int> mp[maxn];
10 int vis[maxn];
11 int sonSum[maxn], leftSum[maxn];
12 int sonMax[maxn], ans[maxn];
13 int find_son_co(int fa)
14 {
15     vis[fa] = 1; sonSum[fa] = 1;
16     bool flag = false;
17     for(int i = 0; i < mp[fa].size(); i++)
18     {
19         if(vis[mp[fa][i]]) continue;
20         flag = true;
21         int temp = find_son_co(mp[fa][i]);
22         if(temp >= sonMax[fa]) sonMax[fa] = temp;
23         sonSum[fa] += temp;
24     }
25     return sonSum[fa];
26 }
27 int main() 
28 {
29   //  freopen("in.txt", "r", stdin);
30     scanf("%d", &T);
31     while(T--)
32     {
33         scanf("%d", &N);
34         for(int i = 1; i <= N; i++) mp[i].clear();
35         for(int i = 1; i <= N-1; i++)
36         {
37             int a, b; scanf("%d%d", &a, &b);
38             mp[a].push_back(b);
39             mp[b].push_back(a);
40         }
41         memset(vis, 0, sizeof(vis));
42         memset(sonSum, 0, sizeof(sonSum));
43         memset(sonMax, 0, sizeof(sonMax));
44         find_son_co(1);
45         for(int i = 1; i <= N; i++)
46         {
47             leftSum[i] = N - sonSum[i];
48         }
49         int mmin = 0x3f3f3f3f; int pos;
50         for(int i = 1; i <= N; i++)
51         {
52             int temp = max(leftSum[i], sonMax[i]);
53             if(temp <= mmin)
54             {
55                 pos = i; mmin = temp;
56             }
57         }
58         printf("%d %d\n", pos, mmin);
59     }
60     return 0;
61 }

 

posted @ 2015-10-15 16:48  下周LGD该赢了吧  阅读(149)  评论(0编辑  收藏  举报