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

 

posted @ 2017-04-21 21:47  Lorazepam  阅读(332)  评论(0编辑  收藏  举报