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:
Sample Output 1:
Sample Input 2:
Sample Output 2:
并查集的相关资料前面已经有介绍了,所以用并查集判断是否是树很简单,然后就是最长根的查找,这里用的是dfs,其实bfs更容易解该问题。查找最长根的时候,首先从一点进行深搜,把其中距离最远的点记录下来(可访问到所有顶点,因为已经保证是树),然后从这些最远点中任选一点再进行深度搜索,这个时候的所有最远点都是最长根,关键是第一遍dfs保存的最远点也是最长根,这个地方最难理解了,首先,若第一遍dfs后的最远根不在从1开始的同一条支路上(他们的最近公共祖先是1),这是这些点必定都会是将来的最长根这很明显,若第一遍dfs后的最远根在从1开始的同一条支路上(他们的最近公共祖先不是1记为f),则第二遍dfs时的最长根所在的dfs遍历序列必过f,所以此时的情况又可将f点看做第一种情况中的1节点类似。综上第一次与第二次dfs的合集才是最终结果。
[/code]
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]
相关文章推荐
- POJ 2318 TOYS(计算几何)
- HDU 2012 素数的判定
- hdoj 2043密码
- 代码大全2-三思而后行:前期准备
- JSON.stringify 语法实例讲解
- leetCode 96.Unique Binary Search Trees (唯一二叉搜索树) 解题思路和方法
- Linux网络编程select模型的实现
- ADB not responding
- C++易vector
- sublime text 3 快捷键大全以及配置编译环境
- UVA 10061 How many zeros and how many digits?
- 模版小结2
- MFC中获得对话框控件相对于父窗口的位置
- 求约数 hdu2601 An easy problem
- Highcharts帮助文档和实际代码不一致
- 暑假- Trie树-(D - Phone List)
- Android Volley完全解析(一),初识Volley的基本用法
- Matlab--多项式
- 讲解如何在Unity的Inspector面板实现类似摄像机层次遮罩的多选效果
- Swift学习记录(Swift和Object-C混编之可选值类型的选择)