您的位置:首页 > 其它

POJ1655树的重心 问删除哪个点,使余下的各个子树结点个数的最大值最小.

2015-08-30 21:36 323 查看
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define  nMax 20010

struct Edge{
int v;
int next;
}edge[2 * nMax];//保存双向图
int preEdge[nMax];//同一个起点的上一条边
int n;
bool flag[nMax];
int childNum[nMax];//每个节点下的节点总数
int min;
int childMax[nMax];//每个节点去掉后其他子树最多点数

int dfs(int root)
{
flag[root] = true;
int p = preEdge[root];//以root为起点的边的标示也就是edge的下标

while (p)
{
int v = edge[p].v;//root连接的点
if (!flag[v])
{
childNum[root] += dfs(v);//求root点下的所有节点
childMax[root] = Max(childNum[edge[p].v], childMax[root]);//求root点下孩子节点中的最大值
}
p = edge[p].next;//以root为起点的上一条边
}
childMax[root] = Max(n - childNum[root], childMax[root]);//root下孩子节点中的最大值和祖先节点总数的最大值作为本节点的最大值
return childNum[root];//返回本节点的总数
}

int  main()
{
int t;
int u, v;
while (scanf("%d", &t) != EOF)
{
while (t --)
{
memset(preEdge, 0, sizeof(preEdge));
memset(flag, false, sizeof(flag));
min = 0x0FFFFFFF;
scanf("%d", &n);
for (int i = 1; i < 2 * (n - 1); i += 2)//建图
{
scanf("%d %d", &u, &v);
edge[i].v = v;
edge[i].next = preEdge[u];
preEdge[u] = i;

edge[i + 1].v = u;
edge[i + 1].next = preEdge[v];
preEdge[v] = i + 1;
}
if (n == 1)
{
printf("1 0\n");
continue;
}
//memset(childNum, 0, sizeof(childNum));
for (int i = 1; i <= n; ++ i)
{
childNum[i] = 1;
childMax[i] = -1;
}
dfs(1);//dfs
int mMin = 0x0FFFFFFF, k;
for (int i = 1; i <= n; ++ i)//求最小值
{
if (mMin > childMax[i])
{
k = i;
mMin = childMax[i];
}
}
printf("%d %d\n", k, mMin);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: