uva 10459 The Tree Root (树的中心)

Problem G

The Tree Root

Input: standard input

Output: standard output

Time Limit: 4 seconds

 

Tree is an important data structure. Searching is a basic operation in any data structure. In a tree searching mainly depends on its height. Consider the following three trees.

If you observe carefully, you will see that all trees are same except different nodes are used as roots. Here the height of the tree varies with the selection of the root. In the 1st tree root is '2' and height is 3. In 2nd one root is '1' and height is 2. And in last one root is '4' and height is 4. We will call '1' best root as it keeps the tree with the least possible height and '4' worst root for the opposite reason.

In this problem, you have to find out all best roots and worst roots for a given tree.

 

Input

Each dataset starts with a positive integer N(3<=N<=5000), which is the number of nodes in the tree. Each node in the tree has a unique id from 1 to N. Then successively for each i'th node there will be a positive integer K[i] following id of K[i] nodes which are adjacent to i. Input is terminated by EOF.

Output

For each dataset print two lines. In the 1st line show all the best roots in ascending order and in next line show all worst roots in ascending order. See sample output for exact format.

 

Sample Input

 7 2 2 3 3 1 6 7 3 1 4 5 1 3 1 3 1 2 1 2 

Sample Output

 Best Roots : 1 Worst Roots : 4 5 6 7 

Author : Md. Kamruzzaman

The Real Programmers' Contest-2


这道题要求树的“中心”,和“worst root”。所谓树的“中心”:想辦法選定一個樹根,讓樹的高度最小。

通过这题,学了一个新姿势。参考http://www.cnblogs.com/wally/p/3311768.html。
先问这样一个问题:求树上每个节点到树上其他节点的最远距离。解法:因为可以证明树上任意某个节点到树上任意节点的最远距离的端点一定会是树上直径的两个端点之一。所以只需要找出任意一对直径的两个端点,分别以它们为根求到其他点的距离,并更新每个点的最远距离。具体做法就是先任意一次dfs求出树上最长直径的一个端点End,然后以该端点为起点再次dfs求出另一个端点,然后再次以求出的另一个端点为起点dfs,每次做dfs的时候都更新dist[](dist[u]表示u到树上任意节点的最远距离)。
对这个题来说,有了dist数组后,dist最小的点对应的就是中心(当直径长度为偶数时,有两个),最远的dist是直径,对应的点是worst root。至此,题目解决。
#include<cstdio>
#include<map>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<cmath>
using namespace std;
const int maxn = 5000 + 5;
const int INF = 1000000000;
const double eps = 1e-6;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> P;
#define fi first
#define se second

vector<int> G[maxn];
int dis[maxn];
int e, maxd;

void dfs(int now, int fa, int dep){
    dis[now] = max(dis[now], dep);
    if(dis[now] > maxd){//当maxd更新的时候,更改直径的端点e
        maxd = dis[now];
        e = now;
    }
    for(int i = 0;i < G[now].size();i++){
        int to = G[now][i];
        if(to != fa)
            dfs(to, now, dep+1);
    }
}

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        for(int i = 1;i <= n;i++){
            G[i].clear();
            int num, x;
            scanf("%d", &num);
            while(num--){
                scanf("%d", &x);
                G[i].push_back(x);
            }
        }
        memset(dis, 0, sizeof dis);
        e = 1, maxd = 0;
        dfs(e, 0, -1);
        dfs(e, 0, -1);
        dfs(e, 0, -1);
        int mind = INF;
        for(int i = 1;i <= n;i++)
            mind = min(mind, dis[i]);
        printf("Best Roots  :");
        for(int i = 1;i <= n;i++){
            if(dis[i]==mind)
                printf(" %d", i);
        }
        puts("");
        printf("Worst Roots :");
        for(int i = 1;i <= n;i++){
            if(dis[i]==maxd)
                printf(" %d", i);
        }
        puts("");
    }
    return 0;
}
/*
3
1 2
2 1 3
1 2
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值