Pat(Advanced Level)Practice--1021(Deepest Root)

来源:互联网 发布:ubuntu samba 写权限 编辑:程序博客网 时间:2024/05/23 11:39

Pat1021代码

题目描述:

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

AC代码:
题目是要判断图是否都连接构成树,求使树高最大的所有的根,实际上求图上两点间最大距离。
参考网上程序,发现树的最长路径其实有个很方便的求法。任取一个点x,求出距离x最远的一个点y,然后求出距离y最远的一个点z。y到z就是一条最长路径。他是先用并查集判断共有几个部分,再bfs求距离,先任取一点开始bfs,得到最远的叶节点,以此叶节点再bfs可得。
#include<cstdio>#include<vector>#include<queue>#include<map>#define MAX 10005using namespace std;int dis[MAX];vector<int> adj[MAX];int parent[MAX];int n;int Find(int x){int p=x;while(p!=parent[p])p=parent[p];return p;}void Union(int x,int y){int fx,fy;fx=Find(x);fy=Find(y);if(fx!=fy)parent[fx]=fy;}int BFS(int start){for(int i=1;i<=n;i++)dis[i]=-1;queue<int> q;q.push(start);dis[start]=0;int maxdis=0;while(!q.empty()){int cur=q.front();for(int i=0;i<adj[cur].size();i++){int temp=adj[cur][i];if(dis[temp]<0){q.push(temp);dis[temp]=dis[cur]+1;if(dis[temp]>maxdis)maxdis=dis[temp];}}q.pop();}return maxdis;}int main(int argc,char *argv[]){int i,j;scanf("%d",&n);for(i=1;i<=n;i++)parent[i]=i;for(i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);adj[x].push_back(y);adj[y].push_back(x);Union(x,y);}int count=0;for(i=1;i<=n;i++)if(parent[i]==i)count++;if(count>1)printf("Error: %d components\n",count);else{map<int,int> m;int max=BFS(1);int index,first=1;for(i=1;i<=n;i++){if(dis[i]==max&&first){index=i;m[i]++;first=0;}else if(dis[i]==max)m[i]++;}max=BFS(index);dis[i]=max;for(i=1;i<=n;i++)if(dis[i]==max)m[i]++;map<int,int>::iterator it;for(it=m.begin();it!=m.end();it++)printf("%d\n",it->first);}return 0;}

其实,这题比较难理解的是第一次BFS的最远点也是deepest root;下面简单的证明一下:
假设从A点开始BFS找到一个最远点C,树中其中一个deep root是从X到Z,那么就有
     A---------------------->C
X-------------------------->Z
因为这是一棵树那么必然AC与XZ有交点,否则就不是一个树了,于是
     A-------B------------->C 
X-----------B------------->Z ( 就这样吧实在没法画图)
假设AC与XZ相交于B点,那么必然有BC等于BZ;
如果两者不相等,便不满足1,C是距离A最远的点;2,XZ距离在整棵树中最远;
因此C也是deepest root,也就是说第一次BFS得到的最远点也是deepest root,所以结果就是第一次BFS和
第二次BFS的并集;
(PS:这题用两次BFS与两次DFS都可以,因为求的是最远距离)
2 0
原创粉丝点击