1021 Deepest Root (25分)

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 (≤10^4
) 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

解释

给你一个无向图,找到能够使得遍历深度最深的那一些结点,如果有多个,就按结点的序号从小到大输出。

思路

所以最暴力的想法是以所有的点为根来n遍dfs,最后找到里面深度最深的那一些点,就好了。
还有一种只需要两遍dfs就可以的,就是第一次从1号点dfs,然后从里面得到深度最深的点集s1,然后在从s1中任选一个点dfs,在得到深度最深的点集s2,答案是s1和s2的并集(这个方法要证明一下,有点类似树的直径那一题)。
连通图用并查集判断。

暴力代码

#include<iostream>
#include<cstring>
#include<vector>

using namespace std;

const int N = 10010, M = 20010;

int p[N];
int n;
int h[N], e[M], ne[M], idx;
int w[N], vis[N], mx;

int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void dfs(int u, int d){
    mx = max(mx, d);
    vis[u] = 1;
    for(int i = h[u]; i != -1; i = ne[i]){
        if(vis[e[i]] == 0) dfs(e[i], d + 1);
    }
}

int main(){
    memset(h, -1, sizeof h);
    
    cin >> n;
    
    for(int i = 1; i <= n; i ++) p[i] = i;
    
    for(int i = 1; i < n; i ++){
        int a, b;
        cin >> a >> b;
        add(a, b); add(b, a);
        if(find(a) != find(b)) p[find(b)] = p[find(a)];
    }
    
    int cnt = 0;
    for(int i = 1; i <= n; i ++) if(p[i] == i) cnt ++;
    if(cnt > 1){
        printf("Error: %d components", cnt);
        return 0;
    }
    
    for(int i = 1; i <= n; i ++){
        mx = 0;
        memset(vis, 0, sizeof vis);
        dfs(i, 0);
        w[i] = mx;
    }
    
    for(int i = 1; i <= n; i ++) mx = max(mx, w[i]);
    
    vector<int> res;
    
    for(int i = 1; i <= n; i ++)
        if(mx == w[i]) res.push_back(i);
        
    for(auto t : res) cout << t << endl;
    
    return 0;
}

两遍dfs代码

#include<iostream>
#include<cstring>
#include<set>

using namespace std;

const int N = 100010, M = 200010;

int p[N];
int n;
int h[N], e[M], ne[M], idx;
int w[N], vis[N], mx;

int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void dfs(int u, int d){
    w[u] = d;
    mx = max(mx, d);
    vis[u] = 1;
    for(int i = h[u]; i != -1; i = ne[i]){
        if(vis[e[i]] == 0) dfs(e[i], d + 1);
    }
}

int main(){
    memset(h, -1, sizeof h);
    
    cin >> n;
    
    for(int i = 1; i <= n; i ++) p[i] = i;
    
    for(int i = 1; i < n; i ++){
        int a, b;
        cin >> a >> b;
        add(a, b); add(b, a);
        if(find(a) != find(b)) p[find(b)] = p[find(a)];
    }
    
    int cnt = 0;
    for(int i = 1; i <= n; i ++) if(p[i] == i) cnt ++;
    if(cnt > 1){
        printf("Error: %d components", cnt);
        return 0;
    }
    
    dfs(1, 0);
    
    set<int> res;
    
    for(int i = 1; i <= n; i ++) 
        if(mx == w[i]) res.insert(i);
        
    mx = 0;
    memset(vis, 0, sizeof vis);
    dfs(*res.begin(), 0);
    
    for(int i = 1; i <= n; i ++)
        if(mx == w[i]) res.insert(i);
        
    for(auto t : res) cout << t << endl;
    
    return 0;
}
posted @ 2020-08-02 09:53  yys_c  阅读(121)  评论(0编辑  收藏  举报