您的位置:首页 > 其它

1021. Deepest Root (25)

2015-07-28 10:50 316 查看
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或者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 10010
struct 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的合集才是最终结果。

[/code]




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: