不用說這兩位都是冷門算法……畢竟O(n^3)的時間復雜度算法在算法競賽里基本算是被淘汰了……而且也沒有在這個算法上繼續衍生出其他的算法…
話說學離散的時候曾經有個把warshall算法簡化到1/2時間的想法……不過懶得去翻了,現在想想本來這兩個不用矩陣而用位運算的話速度不知道比我那個方法快多少倍……
嘛,切入正題吧,先講warshall算法,其用來計算有向圖的傳遞閉包,不知道概念的請去百度(躺
之前在學離散的時候還是花了點時間來研究這個算法的,但是仔細看了下書上的就發現和書上寫的有些不一樣,下面講講我知道的那種和書上的那種:
我知道的那種:
將有向圖的鄰接矩陣進行相乘操作,每乘一次保存結果,原本的矩陣稱為R(1),再乘以R(1)稱為R(2),再乘以R(1)稱為R(3)…直到取到R(n-1)為止。將R1….Rn-1取並,得出相連矩陣結果。
原理,易證,將鄰接矩陣相乘所得為比當前路線高一階的相連矩陣,假設R1為所有路徑為1的通路,那么R2就是所有路徑為2的通路。。。Rn-1就是所有路徑為n-1的通路。因為只有n個節點,假設求得路線不存在環,那最多為n-1長度,可從之前結果獲得,假設存在環,那么環的結果再之前便已經取得。無論怎樣,其並結果絕對包含所有節點的鏈接關系。
書上新看到的:
for k in vertex
for i in row
for j in col
如果點i,k.col存在相連關系,k.row,j存在相連關系,那么這個點就是可以被連上的。
同樣的,floyd也是這個尿性,不過里面得改一下:
若能相連,看看是不是比現在的值小,小的就換上。
嘛,怎么說肯定不是很理解,所以我就用例子說明一下把:
這樣的一張圖,鄰接矩陣的樣式為:
a b c d
a 0 n 3 n
b 2 0 n n
c n 7 0 1
d 6 n n 0
布爾值的樣式是:
a b c d
a 0 n 1 n
b 1 0 n n
c n 1 0 1
d 1 n n 0
那么,warshall的做法是,先統計第1行和第1列,發現(d,c)列對應的(a,c)(第一行),和(d,a)(第一列)都為1,則(d,c)變為1,同理,(b,c)變為1,那么第一輪的結果是:
a b c d
a 0 n 1 n
b 1 0 1 n
c n 1 0 1
d 1 n 1 0
第二輪:
a b c d
a 0 n 1 n
b 1 0 1 n
c 1 1 1 1
d 1 n 1 0
第三輪:
a b c d
a 1 1 1 1
b 1 1 1 1
c 1 1 1 1
d 1 1 1 1
至此,已經沒有進行第四輪的必要,故這是一個全通圖。floyd的思路與其類似,不過是判斷是否兩個關聯值加起來是否小於當前值,小於的話那就更新,不然不更新。