pat 1021. Deepest Root (25)
2016-07-25 09:10
591 查看
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 calledthe 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:
解题关键:先用并查集判断是否为树,然后再求树的直径(先随便取一点进行深搜,然后记录所有的最远的点a1,a2,a3......,最后再任取一点ai再进行深搜,记录所有最远的点b1,b2,b3.........,再合并a1,a2,a3......和b1,b2,b3.......
为什么要合并a,b?
查找最长根的时候,首先从一点进行深搜,把其中距离最远的点记录下来(可访问到所有顶点,因为已经保证是树),然后从这些最远点中任选一点再进行深度搜索,这个时候的所有最远点都是最长根,关键是第一遍dfs保存的最远点也是最长根,这个地方最难理解了,首先,若第一遍dfs后的最远根不在从1开始的同一条支路上(他们的最近公共祖先是1),这是这些点必定都会是将来的最长根这很明显,若第一遍dfs后的最远根在从1开始的同一条支路上(他们的最近公共祖先不是1记为f),则第二遍dfs时的最长根所在的dfs遍历序列必过f,所以此时的情况又可将f点看做第一种情况中的1节点类似。综上第一次与第二次dfs的合集才是最终结果。http://blog.csdn.net/iaccepted/article/details/20454519
输入样例:
5
1 2
1 3
2 4
2 5
输出样例
3
4
5
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
解题关键:先用并查集判断是否为树,然后再求树的直径(先随便取一点进行深搜,然后记录所有的最远的点a1,a2,a3......,最后再任取一点ai再进行深搜,记录所有最远的点b1,b2,b3.........,再合并a1,a2,a3......和b1,b2,b3.......
为什么要合并a,b?
查找最长根的时候,首先从一点进行深搜,把其中距离最远的点记录下来(可访问到所有顶点,因为已经保证是树),然后从这些最远点中任选一点再进行深度搜索,这个时候的所有最远点都是最长根,关键是第一遍dfs保存的最远点也是最长根,这个地方最难理解了,首先,若第一遍dfs后的最远根不在从1开始的同一条支路上(他们的最近公共祖先是1),这是这些点必定都会是将来的最长根这很明显,若第一遍dfs后的最远根在从1开始的同一条支路上(他们的最近公共祖先不是1记为f),则第二遍dfs时的最长根所在的dfs遍历序列必过f,所以此时的情况又可将f点看做第一种情况中的1节点类似。综上第一次与第二次dfs的合集才是最终结果。http://blog.csdn.net/iaccepted/article/details/20454519
输入样例:
5
1 2
1 3
2 4
2 5
输出样例
3
4
5
#include<iostream> #include<string.h> #include<stack> #include<vector> using namespace std; #include<stdio.h> #include<algorithm> #include<queue> #define MS(a,b) memset(a,b,sizeof(a)) vector<int>tree[30000]; int ans[10005],fa[10005],g[10005],j,mm,vis[10005]; int findx(int x) { int r=x; if(r!=fa[r]) fa[r]=findx(fa[r]); return fa[r]; } void Union(int x,int y) { int tx,ty; tx=findx(x);ty=findx(y); if(tx!=ty) fa[tx]=ty; } void dfs(int u,int depth) { int i; if(tree[u].size()==0)return ; for(i=0;i<tree[u].size();i++) { if(!ans[tree[u][i]])//如果该节点深度未知 { ans[tree[u][i]]=depth;//记录该节点的深度。 dfs(tree[u][i],depth+1);//搜索该节点的子节点。 } } } int main() { int n,a,b,i,num,c,d; cin>>n; for(i=1;i<=n;i++) fa[i]=i; for(i=1;i<n;i++) { cin>>a>>b; tree[a].push_back(b); tree[b].push_back(a); Union(a,b); } num=0; for(i=1;i<=n;i++) if(fa[i]==i)num++; if(num!=1) printf("Error: %d components\n",num); else { mm=-1;j=0; MS(ans,0); ans[1]=1; dfs(1,2); for(i=1;i<=n;i++) { if(mm<ans[i]) mm=ans[i],c=i; } for(i=1;i<=n;i++) if(ans[i]==mm) g[j++]=i; MS(ans,0); mm=-1; ans[c]=1; dfs(c,2); for(i=1;i<=n;i++) if(mm<ans[i]) mm=ans[i]; for(i=1;i<=n;i++) if(ans[i]==mm) g[j++]=i; sort(g,g+j); MS(vis,0); for(i=0;i<j;i++) if(!vis[g[i]]) { vis[g[i]]=1; printf("%d\n",g[i]); } } return 0; }
相关文章推荐
- Scala面向对象学习
- “Options模式”下的配置是如何绑定为Options对象
- 无人机领域小神器,P440超宽带射频模块表现这么给力
- Node.js安装配置
- 【转】移动端轮播插件,zepto轮播插件
- Android EditText 取消输入框弹出
- jdbc连接MySQL数据库
- Hadoop:启动与停止命令
- 关于actionMode 6.0适配问题
- POJ——2002——Squares
- 如何在Linux的桌面上创建快捷方式或启动器
- 【缓存技术原理】浏览器端缓存机制详解
- 雷鸣决定第三次创业,做一件人工智能和教育结合的事,成立一家叫“快乐智慧”的公司
- cocos2d - JS Rect 相关
- Swift基础(十七)UITextView
- 三个和尚的故事
- 关于整型和浮点型的输出问题
- map的详细用法
- WPF功能点
- hadoop怎么安装配置