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;
}