POJ 3099 Go Go Gorelians
http://poj.org/problem?id=3099
树的重心:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心
求树的重心
如何在点中构造符合条件的树
得到树后 从任意一个点出发 dfs一次找到离这个点最远的点作为root1
在以root1出发 同样的方式求得root2
root1-root2就是这个树的直径 那么中心必然在这个直径上, 如果直径上点的个数是奇数的话那么 这个点就是重心 否则有两个重心 分别输出
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 #include <vector> 5 #include <math.h> 6 #define MAXN 1007 7 8 using namespace std; 9 10 int dp[MAXN]; 11 int id[MAXN]; 12 int pre[MAXN]; 13 double dist[MAXN][MAXN]; 14 double x[MAXN], y[MAXN], z[MAXN]; 15 int path[MAXN]; 16 int n; 17 vector<int> G[MAXN]; 18 19 double getdis(int i, int j) 20 { 21 double dx = x[i] - x[j]; 22 double dy = y[i] - y[j]; 23 double dz = z[i] - z[j]; 24 return sqrt(dx*dx+dy*dy+dz*dz); 25 } 26 27 void build() 28 { 29 for(int i = 0; i < n; i++) 30 { 31 double dis = 0x3fffffff; 32 int obj = -1; 33 for (int j = 0; j < i; j++) 34 { 35 if (dist[id[i]][id[j]] < dis) 36 { 37 dis = dist[id[i]][id[j]]; 38 obj = j; 39 } 40 } 41 if (obj == -1) continue; 42 int u = id[i], v = id[obj]; 43 G[u].push_back(v); 44 G[v].push_back(u); 45 } 46 } 47 void dfs(int x, int par, int len) 48 { 49 dp[x] = len; 50 for (int i = 0; i < G[x].size(); i++) 51 { 52 if (G[x][i] != par) 53 dfs(G[x][i], x, len+1); 54 } 55 56 } 57 58 59 void dfs1(int x, int par, int len) 60 { 61 dp[x] = len; 62 pre[x] = par; 63 for (int i = 0; i < G[x].size(); i++) 64 { 65 if(G[x][i] != par) 66 dfs1(G[x][i], x, len+1); 67 } 68 } 69 int main() 70 { 71 while (~scanf("%d", &n)) 72 { 73 if (n == 0) break; 74 memset(dp, 0, sizeof(dp)); 75 memset(path, 0, sizeof(path)); 76 memset(dist, 0, sizeof(dist)); 77 memset(pre, 0, sizeof(pre)); 78 for (int i = 0; i < MAXN; i++) 79 G[i].clear(); 80 for (int i = 0; i < n; i++) 81 { 82 scanf("%d%lf%lf%lf", &id[i], &x[i], &y[i], &z[i]); 83 } 84 for (int i = 0; i < n; i++) 85 for (int j = 0; j < n; j++) 86 dist[id[i]][id[j]] = getdis(i, j); 87 build(); 88 dfs(id[0], -1, 0);//权值都为1 89 int tmp = 0; 90 //找到离节点最远的节点 得到root1 91 int root1, root2; 92 for (int i = 0; i < n; i++) 93 { 94 if ( dp[id[i]] > tmp) 95 { 96 tmp = dp[id[i]]; 97 root1 = id[i]; 98 } 99 } 100 memset(dp, 0, sizeof(dp)); 101 dfs1(root1, -1, 0); 102 tmp = 0; 103 for (int i = 0; i < n; i++) 104 { 105 if (dp[id[i]] > tmp) 106 { 107 tmp = dp[id[i]]; 108 root2 = id[i]; 109 } 110 }//找到root2; 111 int s = 0; 112 for(int i = root2; i != -1; i = pre[i]) 113 { 114 path[++s] = i; 115 } 116 int mid = (s+1)/2; 117 if (s % 2 == 1) 118 { 119 printf("%d\n", path[mid]); 120 } 121 else 122 { 123 int a = path[mid], b = path[mid+1]; 124 printf("%d %d\n", min(a, b), max(a, b)); 125 } 126 127 } 128 129 return 0; 130 }
关于树的重心更多的内容
转载 :http://www.cnblogs.com/patrickzhou/p/5867208.html