poj 1655 Balancing Act 求树的重心【树形dp】
题意:求树的重心且编号数最小
一棵树的重心是指一个结点u,去掉它后剩下的子树结点数最少。
(图片来源: PatrickZhou 感谢博主)
看上面的图就好明白了,不仅要考虑当前结点子树的大小,也要“向上”考虑树的大小。
那么其它就dfs完成就行了,son[] 存以前结点为根的结点个数。
这是用邻接表写:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 20006; 7 const int INF = 1 << 30; 8 int head[maxn]; 9 int son[maxn]; 10 bool vis[maxn]; 11 int n,siz, cnt, num; 12 struct Edge 13 { 14 int to, next; 15 }; 16 Edge edge[maxn*2]; 17 18 void Init() 19 { 20 memset(vis, 0, sizeof(vis)); 21 memset(head, -1, sizeof(head)); 22 siz =num= INF; 23 cnt = 0; 24 } 25 26 27 void add(int u, int v) 28 { 29 edge[cnt].to = v; 30 edge[cnt].next = head[u]; 31 head[u] = cnt++; 32 } 33 34 void dfs(int u) 35 { 36 vis[u] = 1; 37 son[u] = 1; 38 int tmp = 0; 39 for (int i = head[u]; i != -1; i = edge[i].next) 40 { 41 int v = edge[i].to; 42 if (!vis[v]) { 43 dfs(v); 44 son[u] += son[v]; 45 tmp = max(tmp, son[v]); 46 } 47 } 48 tmp = max(tmp, n - son[u]); 49 if (tmp < siz || (tmp == siz&&u < num)) { 50 siz = tmp; 51 num = u; 52 } 53 } 54 55 int main() 56 { 57 int T; 58 cin >> T; 59 while (T--) 60 { 61 cin >> n; 62 Init(); 63 for (int i = 1; i < n; i++) { 64 int u, v; 65 cin >> u >> v; 66 add(u, v); 67 add(v, u); 68 } 69 dfs(1); 70 cout << num << " " << siz << endl; 71 } 72 return 0; 73 }
这题用stl不超时:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 #include<algorithm> 6 using namespace std; 7 const int maxn = 20006; 8 const int INF = 1 << 30; 9 vector<int> tree[maxn]; 10 int son[maxn]; 11 int n, siz,num; 12 13 void dfs(int u, int fa) 14 { 15 son[u] = 1; 16 int tmp = 0; 17 for (int i = 0; i < tree[u].size(); i++) { 18 int v = tree[u][i]; 19 if (v != fa) { 20 dfs(v,u); 21 son[u] += son[v]; 22 tmp = max(tmp, son[v]); 23 } 24 } 25 tmp = max(tmp, n - son[u]); 26 if ((tmp < siz) || (tmp == siz&&u > num)) { 27 siz = tmp; 28 num = u; 29 } 30 } 31 32 int main() 33 { 34 int T; 35 cin >> T; 36 while (T--) 37 { 38 cin >> n; 39 for (int i = 0; i <= n; i++) tree[i].clear(); 40 for (int i = 1; i < n; i++) { 41 int u, v; 42 cin >> u >> v; 43 tree[u].push_back(v); 44 tree[v].push_back(u); 45 } 46 num = 0, siz = INF; 47 dfs(1, -1); 48 cout << num << " " << siz << endl; 49 } 50 return 0; 51 }