无向图的直径以及树的直径
轉載:http://www.csie.ntnu.edu.tw/~u91029/Path3.html
在一張無向圖上面,給定圖上一點,以最短路徑長度當作距離,找出離此點最遠的一點,這兩點之間的距離就叫做「偏心距」。
要計算一張無向圖的直徑與半徑是很簡單的,首先算好所有兩點之間最短路徑,然後按照定義來算就可以了。
先用floyd算法,再找最長的即可
樹形圖的最長路徑(邊無權重)
方法1:
一棵無根樹的「直徑」,就是相離最遠的兩個點的距離。
稍微修改一下計算高度的程式碼,就可以順便計算直徑。
樹的直徑,邊無權重(adjacency matrix)一棵樹的各種直徑一定會相交在同一點(同一群點)。
1. 反證法。 現在有兩條分開的直徑, 可是一棵樹上各點都得連通, 所以這兩條分開的直徑,中間一定有某處互相連接, 一旦連接起來,勢必變成更長的直徑,矛盾。 故所有直徑必相交。2. 反證法。 現在已有兩條直徑相交在某一點, 如果另外一條直徑與這兩條直徑相交在另一點, 勢必變成更長的直徑,矛盾。 故所有直徑必相交在同一點(同一群點)。方法二:
在一個迷宮中找距離最長的兩個點。迷宮可以看作是一個無根樹,因此,這個問題等價與在一個樹形圖中找最遠的兩個節點,也叫做這個圖的直徑。
迷宮、樹形圖有個很好的特點:任意兩個節點之間的距離就是這兩點之間的最短路徑、也是兩個節點的最長路徑,也可以說任意兩個節點之間的距離一定。基于這個想法,可以很快想到:窮舉每個點對,計算其距離,取最大值,即可。這個計算量比較大,思想上可行,實踐起來,時間代價有點不靠譜。查了下,已經有好的解決方案了:
1 取任意節點作為起點,找出到該點最遠的點,記為A;
2 以點A為起點,找出到該點最遠的點,記為B;
AB之間的距離,就是圖中距離最遠的兩個點的距離(這樣的點對可能有多個,但最大距離值只有一個)。
因此,兩次dfs即可搞定。也可以用bfs
代碼如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
?
int m,n;
int f[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
char map[1002][1002];
bool flag[1002][1002];
?
int max,step,maxM,maxN;
int si,sj;
?
void dfs(int i,int j)
{
? ? int ii,a,b;
? ? for(ii=0;ii<4;ii++)
? ? {
? ? ? ? a = i+ f[ii][0];
? ? ? ? b = j+ f[ii][1];
? ? ? ? if(a>=0 && a<m && b>=0 && b<n && map[a][b]=='.' && flag[a][b])
? ? ? ? {
? ? ? ? ? ? step++;
? ? ? ? ? ? flag[a][b] = false;
? ? ? ? ? ? if(max < step)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? max = step;
? ? ? ? ? ? ? ? maxM = a;
? ? ? ? ? ? ? ? maxN = b;
? ? ? ? ? ? }
? ? ? ? ? ? dfs(a,b);
? ? ? ? ? ? flag[a][b] = true;
? ? ? ? ? ? step--;
? ? ? ? }
? ? }
}
int main()
{
? ? int t,i,j;
? ? scanf("%d",&t);
? ? while(t--)
? ? {
? ? ? ? scanf("%d%d",&n,&m);
? ? ? ? si = -1;
? ? ? ? for(i=0;i<m;i++)
? ? ? ? {
? ? ? ? ? ? scanf("%s",map[i]);
? ? ? ? ? ? if(si==-1)
? ? ? ? ? ? ? ? for(j=0;j<n;j++)
? ? ? ? ? ? ? ? ? ? if(map[i][j]=='.')
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? si = i;
? ? ? ? ? ? ? ? ? ? ? ? sj = j;
? ? ? ? ? ? ? ? ? ? ? ? break;;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? }
? ? ? ??
? ? ? ? memset(flag, true, sizeof(flag));
? ? ? ? flag[si][sj] = false;
? ? ? ? max = 0;
? ? ? ? step = 0;
? ? ? ? dfs(si,sj);
? ? ? ??
? ? ? ? memset(flag, true, sizeof(flag));
? ? ? ? flag[maxM][maxN] = false;
? ? ? ? max = 0;
? ? ? ? step = 0;
? ? ? ? dfs(maxM, maxN);
? ? ? ??
? ? ? ? printf("Maximum rope length is %d.\n",max);
? ? }
? ? system("pause");
? ? return 0;
}
如果邊有權重的話,感覺著兩個算法也能正常工作
總結
以上是生活随笔為你收集整理的无向图的直径以及树的直径的全部內容,希望文章能夠幫你解決所遇到的問題。