1021. Deepest Root (25)

原题地址:http://www.patest.cn/contests/pat-a-practise/1021

A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<=10000) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N-1 lines follow, each describes an edge by given the two adjacent nodes’ numbers.

Output Specification:

For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print “Error: K components” where K is the number of connected components in the graph.

Sample Input 1:
5
1 2
1 3
1 4
2 5
Sample Output 1:
3
4
5
Sample Input 2:
5
1 3
1 4
2 5
3 4
Sample Output 2:
Error: 2 components

解题思路:首先用dfs检查给定的图有几个连通分量。题目保证输入无环,则若连通分量只有一个时,可以确定结构为树。从树的任意一点出发,达到的最远距离的节点为此树的最深根。然后,从这些节点中任意一个出发能到达的最远节点亦为最深根。

代码如下:

#include <stdio.h>
#include <cstring>
#include <vector>
#define MAXN 10002

using namespace std;

//int G[MAXN][MAXN];
vector<int> g[MAXN];
int depth[MAXN];
int n;
int vis[MAXN];
int mark[MAXN];
int d_max;
int d_tmp;

int conn(int p,int q){
    for(int i = 0; i < g[p].size(); i++)
        if(g[p][i] == q) return 1;  
    return 0;
}

void dfs_d(int t){
    vis[t] = 1;
    d_tmp++;
    depth[t] = d_tmp;

    for(int i = 0 ; i < n; i++){
        if(conn(t,i) && !vis[i]){
            dfs_d(i);
        }
    }
    if(d_tmp > d_max) d_max = d_tmp;
    d_tmp--;
}

void deep(){
    memset(vis, 0, sizeof(vis));    
    memset(mark, 0, sizeof(mark));  
    d_max = d_tmp = 0;
    dfs_d(0);
    int index = 0;
    int max = 0;
    for(int i = 0; i < n; i++){
        if(max < depth[i]){max = depth[i]; index = i;}
    }
    for(int i = 0; i < n; i++){
        if(max == depth[i]){mark[i] = 1;}
    }
    memset(vis, 0, sizeof(vis));    
    d_max = d_tmp = 0;
    dfs_d(index);
    depth[index] = d_max;
}

void dfs(int t){
    vis[t] = 1;
    for(int i = 0 ; i < n; i++)
        if(conn(t,i) && !vis[i]) dfs(i);
}

int isTree(){
    int count = 0;
        memset(vis,0,sizeof(vis));
        for(int i = 0; i < n; i++){
            if(!vis[i]){
                dfs(i);
                count++;
            }
        }
        return count;
}

int main(){

    freopen("1021.txt","r",stdin);

//  memset(G,0,sizeof(G));
    memset(depth,-1,sizeof(depth));
    scanf("%d",&n);
    for(int i = 0; i < n-1;i++){
        int f, t;
        scanf("%d%d",&f,&t);
        g[t-1].push_back(f-1);
        g[f-1].push_back(t-1);
    }       
    int t = isTree();
    if(t != 1){
        printf("Error: %d components",t);
        return 0;
    }

    deep();
    for(int i = 0; i < n; i++)
        if(d_max == depth[i] || mark[i] == 1) printf("%d\n", i+1);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值