1021. Deepest Root (25)

来源:互联网 发布:蒙泰打印机端口在哪里 编辑:程序博客网 时间:2024/05/18 01:54

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:
51 21 31 42 5
Sample Output 1:
345
Sample Input 2:
51 31 42 53 4
Sample Output 2:
Error: 2 components
——————————————————————
不怎么会做,这道题目。
只会用并查集进行查找是否有环,然后知道用dfs或者bfs进行查找图的直径,没有写成代码。
自己刚刚开始的时候,建立了相应的图,并且进行dfs,但是在递归的过程中,不知道怎么进行。
在这里参考了下,慢慢考虑。
#include <iostream>#include <map>#include <vector>#include <cstdio>#include <set>using namespace std;/* run this program using the console pauser or add your own getch, system("pause") or input loop */#define MAX 10010struct graph{int matrix[MAX][MAX];int num;} *g;int N,cnt, pre[MAX]={0},maxn=-1;bool visited[MAX];map<int,vector<int> > tree;set<int> res;set<int> tres;void dfs(int p, int step){if(step>maxn){res.clear();res.insert(p);maxn=step;}else if(step==maxn){res.insert(p);}vector<int>::iterator ite=tree[p].begin();for(;ite!=tree[p].end();ite++){if(visited[*ite]!=1){visited[*ite]=1;dfs(*ite,step+1);visited[*ite]=0;}}}void init(){for(int i=1; i<=N; i++){pre[i]=i;visited[i]=false;}}int root(int x){if(x != pre[x]){pre[x]=root(pre[x]);}return pre[x];}void merge(int a, int b){int fa=root(a);int fb=root(b);if(fa != fb){pre[fa]=fb;--cnt;}}int main(int argc, char** argv) {set<int>::iterator ite;scanf("%d",&N);cnt=N-1;init();for(int i=1; i<N; i++){int c1,c2;scanf("%d %d",&c1,&c2);tree[c1].push_back(c2);tree[c2].push_back(c1);merge(c1,c2);}if(cnt!=0){printf("Error: %d components\n",cnt+1);return 0; }visited[1]=1;dfs(1,1);visited[1]=0;ite=res.begin();for(;ite!=res.end();ite++){tres.insert(*ite);}int point= *res.begin();visited[point]=1;dfs(point,1);visited[point]=0;ite=res.begin();for(;ite!=res.end();ite++){tres.insert(*ite);}ite=tres.begin();for(;ite!=tres.end();ite++){printf("%d\n",*ite);}return 0;}

并查集的相关资料前面已经有介绍了,所以用并查集判断是否是树很简单,然后就是最长根的查找,这里用的是dfs,其实bfs更容易解该问题。
查找最长根的时候,首先从一点进行深搜,把其中距离最远的点记录下来(可访问到所有顶点,因为已经保证是树),然后从这些最远点中任选一点再进行深度搜索,这个时候的所有最远点都是最长根,关键是第一遍dfs保存的最远点也是最长根,这个地方最难理解了,首先,若第一遍dfs后的最远根不在从1开始的同一条支路上(他们的最近公共祖先是1),这是这些点必定都会是将来的最长根这很明显,若第一遍dfs后的最远根在从1开始的同一条支路上(他们的最近公共祖先不是1记为f),则第二遍dfs时的最长根所在的dfs遍历序列必过f,所以此时的情况又可将f点看做第一种情况中的1节点类似。综上第一次与第二次dfs的合集才是最终结果


                                             
0 0
原创粉丝点击