本博客rss订阅地址: http://feed.cnblogs.com/blog/u/147990/rss

PAT1021 Deepest Root

题目地址:here

题目大意:无环连通图也可以视为一棵树,选定图中任意一点作为根,如果这时候整个树的深度最大,该点称为 deepest root。 给定一个图,按升序输出所有 deepest root。如果给定的图有多个连通分量,则输出连通分量的数量。

解法:先任选一点A从该点开始dfs,找出距离该点最远的点B,则B是一个deepest root;然后从B点开始dfs,找到距离B最远的所有点,这些点加上B点都是deepest root。对于有多个连通分支的,我们可以通过遍历完所有节点调用dfs函数的次数来判断(当然也可以用并查集来求连通分支数目)。                                                                                本文地址

主要是解法中前半段的证明,为什么距离A最远的B是deepest root:

  • 一个概念,定义从deepest root到其最远叶子的路径为树的 “最长路径”
  • 两条最长路径一定有个交点,可以用反证法证明:如果没有交点,由于一棵树中,任意两点都是连通的,可以通过对两条路径组合出一条更长的路径,这与两条路径是最长的矛盾。
  • 假设从A点dfs后,最远的点是B, 假设某一个距离A更近的点D也是deepest root,那么以B、D为端点的最长路径一定有一个交点,假设该交点为k,则有两种情况:(1)最长路径为B....k....D,这种情况和假设不矛盾(2)最长路径为B....k.... 和 D....k....,k后面的路径长度相同。由于A到k一定有一条路径,那么各点之间的关系可以是A...K....D, A....K....B  或者K...A....D,  K...A....B 由于len(A...B)>len(A....D),两种情况下都有:len(B....K) > len(D....K),即len(B....K....) > len(D....K....) 这和D....k....是最长路径矛盾

注意:本题的输入图是默认没有环的

代码如下:                                                                                                             本文地址

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<vector>
 5 #include<algorithm>
 6 using namespace std;
 7 //本题无向图中默认是没有环的
 8 //先任选一点A从该点开始dfs,找出距离该店最远的点B
 9 //然后从B点dfs,找到距离B最远的所有点,这些点加上B点都是deepest root
10 
11 //用邻接表存储图
12 struct GraphNode
13 {
14     vector<int> adja;
15 };
16 
17 bool *visited;
18 GraphNode *graph;
19 
20 //从某个节点开始深度优先遍历图,并求出相应的树的高度,而且保存离树根最远的节点
21 void dfs(int rootIndex, int level, int &height, vector<int> &farthestNode)
22 {
23     visited[rootIndex] = true;
24     if(height < level)
25     {
26         height = level;
27         farthestNode.clear();
28         farthestNode.push_back(rootIndex);
29     }
30     else if(height == level)
31         farthestNode.push_back(rootIndex);
32     for(int i = 0; i < graph[rootIndex].adja.size(); i++)
33     {
34         int son = graph[rootIndex].adja[i];
35         if(visited[son] == false)
36             dfs(son, level+1, height, farthestNode);
37     }
38 }
39 int main()
40 {
41     int N;
42     scanf("%d", &N);
43     if(N == 1){printf("1"); return 0;}
44     graph = new GraphNode[N+1];
45     visited = new bool[N+1];
46     for(int i = 1; i <= N-1; i++)
47     {
48         int a,b;
49         scanf("%d%d", &a, &b);
50         graph[a].adja.push_back(b);
51         graph[b].adja.push_back(a);
52     }
53     vector<int> farthestNode;
54     int height = 0, components = 0;
55     memset(visited, 0, sizeof(bool)*(N+1));
56     //通过dfs遍历整个图来计算图的连通分支,调用dfs的次数就是连通分支数目
57     for(int i = 1; i <= N; i++)
58         if(visited[i] == false)
59         {
60             visited[i] == true;
61             dfs(i, 0, height, farthestNode);
62             components++;
63         }
64     if(components > 1)
65         printf("Error: %d components",components);
66     else
67     {
68         int k = farthestNode[0];
69         farthestNode.clear();
70         height = 0;
71         memset(visited, 0, sizeof(bool)*(N+1));
72         dfs(k, 0, height, farthestNode);
73         farthestNode.push_back(k);
74         sort(farthestNode.begin(), farthestNode.end());
75         for(int i = 0; i < farthestNode.size(); i++)
76             printf("%d\n", farthestNode[i]);
77     }
78     return 0;
79 }

 【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3401764.html

posted @ 2013-11-01 14:00  tenos  阅读(2577)  评论(1编辑  收藏  举报

本博客rss订阅地址: http://feed.cnblogs.com/blog/u/147990/rss

公益页面-寻找遗失儿童