码迷,mamicode.com
首页 > 其他好文 > 详细

树的直径

时间:2014-12-15 00:05:15      阅读:359      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   ar   color   os   sp   for   strong   

*总结的别人博客


树的直径(Diameter)是指树上的最长简单路。
直径的求法:两遍BFS (or DFS)
任选一点u为起点,对树进行BFS遍历,找出离u最远的点v
以v为起点,再进行BFS遍历,找出离v最远的点w。则v到w的路径长度即为树的直径
*简单证明
于是原问题可以在O(E)时间内求出

关键在于证明第一次遍历的正确性,也就是对于任意点u,距离它最远的点v一定是最长路的一端。
如果u在最长路上,那么v一定是最长路的一端。可以用反证法:假设v不是最长路的一端,则存在另一点v’使得(u→v’)是最长路的一部分,于是len(u→v’) > len(u→v)。但这与条件“v是距u最远的点”矛盾。
如果u不在最长路上,则u到其距最远点v的路与最长路一定有一交点c,且(c→v)与最长路的后半段重合(why?),即v一定是最长路的一端

bubuko.com,布布扣BFS

 

 

bubuko.com,布布扣DFS 

 

一张无向图中,给定图中一点,以最短路径长度当作距离,找出改点最远的一点,这两点之间的距离就叫做偏心距。

要计算一张无向图的半径,只要先算好两点之间最短路径,然后按定义来算即可。

先用floyd  再搜索最长的路径(即为直径)。

bubuko.com,布布扣
 1 int d[10][10];  // adjacency matrix
 2 int ecc[10];    // 各點的偏心距
 3  
 4 void diameter_radius()
 5 {
 6     // Floyd-Warshall Algorithm
 7     for (int k=0; k<10; ++k)
 8         for (int i=0; i<10; ++i)
 9             for (int j=0; j<10; ++j)
10                 d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
11  
12     // 計算偏心距
13     memset(ecc, 0x7f, sizeof(ecc));
14     for (int i=0; i<10; ++i)
15         for (int j=0; j<10; ++j)
16             ecc[i] = min(ecc[i], d[i][j]);
17  
18     // 計算直徑和半徑
19     int diameter = 0;
20     int radius = 1e9;
21     for (int i=0; i<10; ++i)
22     {
23         diameter = max(diameter, ecc[i]);
24         radius   = min(radius  , ecc[i]);
25     }
26  
27 /*
28     // 直徑也可以這樣算
29     for (int i=0; i<10; ++i)
30         for (int j=0; j<10; ++j)
31             diameter = max(diameter, d[i][j]);
32 */
33 }
floyd

 

一棵樹的各種直徑一定會相交在同一點(同一群點)。

1.
反證法。
現在有兩條分開的直徑,
可是一棵樹上各點都得連通,
所以這兩條分開的直徑,中間一定有某處互相連接,
一旦連接起來,勢必變成更長的直徑,矛盾。
故所有直徑必相交。

2.
反證法。
現在已有兩條直徑相交在某一點,
如果另外一條直徑與這兩條直徑相交在另一點,
勢必變成更長的直徑,矛盾。
故所有直徑必相交在同一點(同一群點)。

 

树的直径

标签:style   blog   http   ar   color   os   sp   for   strong   

原文地址:http://www.cnblogs.com/usedrosee/p/4163920.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!