1021 Deepest Root

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 (104​​) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N1 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和BFS.如果使用DFS方法需要在遍历结束后找出不同路径深度的最大值。而如果使用BFS在遍历结束后的层数就是该根的深度。这里选择DFS较为方便。除此之外,我们还需判断该图能不能形成一个N个结点的树,因为题中保证有N-1条边,根据结论“如果N个结点的图是一个连通图,且有N-1条边,那么这个图就可以形成一棵树”,这样问题就转化为求连通块的个数,用并查集可以实现

主要函数和功能部件

并查集:求连通块的个数
main(): 按题目要求读入图
DFS( int root, int depth,int pre ):DFS用递归来实现,所以需要参数root来记录当前结点,又因为程序要求根的深度,所以需要参数depth来记录当前深度。同时,本题的模型是一个无向图,所以要避免回头访问——跳过回去的边,用pre记录前驱结点可以解决这个问题。

坑点

 

注意并不是一次DFS就可以解决问题,如上图,如果开始结点在A区,那么一次遍历的结果是B区的所有深度最大的结点,只遍历这一次就漏掉了A区的结点,所以在一次遍历之后还要以B区的任一结点为开始结点再遍历一次才能得到全部结果。这里暂时无法提供形式化证明,有待进一步研究。

参考代码

  1 #include<iostream>
  2 #include<vector>
  3 #include<stdio.h>
  4 #include<algorithm>
  5 using namespace std;
  6 
  7 vector<int> adj[10001];
  8 vector<int> temp,ans;
  9 int father[10001];
 10 bool isRoot[10001]={false};
 11 int n;
 12 int maxdepth=0;
 13 
 14 //查找根节点 
 15 int findfather(int x)
 16 {
 17     int a=x;
 18     while(x!=father[x]){
 19         x=father[x];
 20     }
 21     //路径压缩 
 22     while(a!=father[a]){
 23         int z=a;
 24         a=father[a];
 25         father[z]=x;
 26     }
 27     return x;
 28 }
 29 
 30 //合并集合 
 31 void Union(int a,int b)
 32 {
 33     int faA=findfather(a);
 34     int faB=findfather(b);
 35     if(faA!=faB){
 36         father[faA]=faB;
 37     }
 38 }
 39 
 40 //初始化并查集 
 41 void init(int n)
 42 {
 43     for(int i=1;i<=n;i++){
 44         father[i]=i;
 45     }
 46 }
 47 
 48 //求连通块的数量 
 49 int calBlock(int n)
 50 {
 51     int num=0;
 52     for(int i=1;i<=n;i++)
 53     {
 54         isRoot[findfather(i)]=true;
 55     }
 56     for(int i=1;i<=n;i++){
 57         if(isRoot[i]==true){
 58             num++;
 59         }
 60     }
 61     return num;
 62 }
 63 
 64 //DFS用递归来实现,所以需要参数root来记录当前结点,又因为程序要求根的深度,所以
 65 //需要参数depth来记录当前深度。同时本题的模型是一个无向图,所以要避免回头遍历,
 66 //所以要用pre来记录前驱结点。 
 67 void DFS(int u,int depth,int pre)
 68 {
 69     if(depth>maxdepth){
 70         temp.clear();
 71         maxdepth=depth;
 72         temp.push_back(u);
 73     } else if(depth==maxdepth){
 74         temp.push_back(u);
 75     }
 76     for(int i=0;i<adj[u].size();i++){
 77         if(adj[u][i]==pre){
 78             continue;
 79         } else {
 80             DFS(adj[u][i],depth+1,u);
 81         }
 82     }
 83 }
 84 
 85 int main()
 86 {
 87     cin>>n;
 88     init(n);//不能掉了初始化 
 89     for(int i=1;i<n;i++){
 90         int a,b;
 91         cin>>a>>b;
 92         adj[a].push_back(b);
 93         adj[b].push_back(a);
 94         Union(a,b);
 95     }
 96     int sum=calBlock(n);
 97     if(sum!=1){
 98         printf("Error: %d components\n",sum);
 99     } else {
100         DFS(1,1,-1);
101         ans=temp;
102         temp.clear();
103         DFS(ans[0],1,-1);
104         for(int i=0;i<temp.size();i++){
105             ans.push_back(temp[i]);
106         }
107         sort(ans.begin(),ans.end());
108         cout<<ans[0]<<endl;
109         for(int i=1;i<ans.size();i++){
110             if(ans[i]!=ans[i-1]){
111                 cout<<ans[i]<<endl;
112             }
113         }
114     }
115     return 0;
116 }

 

 

 

 

 

 
posted @ 2020-04-02 11:18  TresBienBA  阅读(140)  评论(0)    收藏  举报