類別 |
題目 |
並查集 |
261, 323, 684 |
最短路徑 |
743 |
最小生成樹 |
1135 |
拓撲排序 |
207, 210, 802,310 |
關鍵路徑法 |
|
圖的遍歷 |
133, 332(歐拉路徑), 399, 785, 841, 997, 1042, 1306 |
其它 |
959, 1043, 1161, 1267, 444 |
就不貼題目超鏈接了,可以去請看這裏!!!leetcode題目目錄!!根據題號找對應題目。
歸納總結:
一、圖的遍歷(traversing of graph)
1、主要就是dfs(depth-first search)、bfs(breadth-first search)。
2、樣例代碼,請參考:841. 鑰匙和房間
二、並查集(Union-Find)
1、找老大,老大是自己的頂點是該聯通域的掌門人。
2、集合的合併,如果一條邊的兩個頂點老大一樣,說明這兩個頂點原本就在一個聯通域內,該聯通域內有環;如果一條邊的兩個頂點老大不一樣,那麼就要把他們併到一個集合內。
3、最後,老大的數目決定連通域的個數。
4、樣例代碼,請參考:684. 冗餘連接(並查集)
三、拓撲排序(topological sort)
1、採用鄰接表來表示有向圖,抽象成:
(1)一個二維數組,裏面每一個一維數組存以該索引爲頂點的後繼頂點。
(2)一個一維數組 in, 來表示每個頂點的入度數目。
2、我們開始先根據輸入來建立這個有向圖,並將入度數組也初始化好。
3、設置一個stack:
(1)將所有入度爲0的點壓棧。
(2)從棧中退出棧頂元素輸出,並把該頂點引出的所有有向邊刪去,也就是把它的各個鄰接頂點的入度數-1。
(3)將新的入度數爲零的頂點再入堆棧。
(4)重複過程(2)-(3),直到棧爲空。
4、最後,如果已經輸出全部頂點,所有頂點入度數都爲0,說明有向圖中不存在環;如果沒有輸出全部頂點,那麼剩下的頂點中存在入度不爲零的頂點,說明有向圖中存在環。
5、樣例代碼,請參考:207. 課程表(拓撲排序)
四、最小生成樹(minimum spanning tree , MST)
方法1: Kruskal算法
1、先了解一下Kruskal算法的步驟:
(1)設一個有n個頂點的連通網絡爲G(V,E),將所有的邊按照權值從小到大排序。
(2)當在G中選擇一條具有最小權值的邊時,若該邊的兩個頂點落在不同的連通分量上,則將此邊加入到T中;否則,即這條邊的兩個頂點落在同一個連通分量上,會形成環,則將此邊捨去,重新選擇下一條權值最小的邊;如何判斷兩個頂點是否落在同一個聯通分量上,採用並查集來解決。
(3)如此重複下去,直到所有頂點在同一個連通分量上爲止。T就是最小生成樹。如果最後T中,不能包含所有頂點,那麼就沒有辦法構成最小生成樹。
2、Kruskal算法=一個排序+並查集
3、樣例代碼,請參考:1135. 最低成本聯通所有城市(最小生成樹)
方法2: prim算法
1、先了解一下Prim算法的步驟:
(1)設一個有n個頂點的連通網絡爲G(V,E), T(U, TE)是最小生成樹。V中存G的頂點,E中存G的邊。U中存T的頂點,TE中存T的邊。開始時,V中是全部頂點。U和TE都是空的。
(2)第一次先從V中隨便取一個頂點加入到U中。
(3)然後從那些其一個端點已經在U中,另一個端點在U外的所有邊中找一條最短的邊。並把該邊和頂點分別併入TE和U中。如此進行下去,每次往生成樹裏併入一個頂點和一條邊,直到n-1次之後,把所有n個頂點都併入U中,此時U=V,T是最小生成樹。如果最後T中,不能包含所有頂點,那麼就沒有辦法構成最小生成樹。
2、樣例代碼,請參考:1135. 最低成本聯通所有城市(最小生成樹)
五、最短路徑(shortest path)
Dijkstra算法(單源最短路徑算法):
1、先了解一下Dijkstra算法的步驟:
(1)設一個有n個頂點的連通網絡爲G, 頂點集合U和T。最開始的時候,U中存G的全部頂點以及源點到這些頂點的路徑長度:源點到自身的路徑長度是0,源點到不相連的頂點,長度是無窮大。T爲空。
(2)每次去U中找出路徑最小的頂點uu,在U中刪掉uu,並且將uu插入到S中。
(3)在U中遍歷從uu出發能到達的所有頂點v,根據U(v)=min(U(v), S(uu)+W[uu,v]),其中W[uu,v])表示uu到v的路徑長度,更新一波U(v)的長度。
(4)重複過程(2)-(3),所有頂點都加入了S中。
2、樣例代碼,請參考:743. 網絡延遲時間(最短路徑)
Prim算法和Dijkstra算法的對比:
1、相同點:都是基於貪心的思想,都是一開始兩個頂點集合A和B,A爲空,B爲全部頂點,都是從B中選一個加入到A中,直到全部頂點加入完成。
2、不同點
(1)Prim算法:每次從那些其一個端點已經在A中,另一個端點在B中的所有邊中找一條最短的邊,加入A中。
(2)Dijkstra算法:每次去B中找出路徑最小的頂點uu,加入A中。
還多一個步驟:要根據uu更新一波B中的最短路徑長度。在B中遍歷從uu出發能到達的所有頂點v,根據B(v)=min(A(v), A(uu)+W[uu,v]),其中W[uu,v])表示uu到v的路徑長度,更新一波B(v)的長度。
六、關鍵路徑法(Critical Path Method, CPM)
1、先了解一下CPM的步驟,核心就是5個for 循環
Ev[i]表示事件i的最早出現時間,E[i]表示活動i的最早出現時間,Lv[i]表示事件i的最遲出現時間,L[i]表示活動i的最遲出現時間。
以j頂點指向k頂點爲例:
(1)從源點開始向匯點遞推,根據Ev[k]=max(Ev[j]+w[j,k]),求出Ev數組。其中的最大值Ev[n]是匯點的最早開始時間。
(2)因爲匯點就是結束點,其最遲出現時間與最早出現時間相同,即Ev[n]=Lv[n]。將(1)中排好序的事件,從匯點開始向源點遞推,根據Lv[j]=min(Lv[k]-w[j,k]),求出Lv數組。
(3)活動的最早開始時間與事件的最早開始時間是一樣的,求出E數組,E=Ev.
(4)j頂點指向k頂點,中間經歷活動aj, 根據L[j]=Lv[k]-(活動j所需的時間),求出L數組。
(5)E[i]=L[i]的活動,就是關鍵活動,由這些活動組成的路徑就是關鍵路徑。
(6)有可能關鍵路徑不止一條,那麼這時候可以將re按照字典序排序,如果後一條路徑的起始點,與前一條路徑的結束點不一致,即x[i][0]!=x[i-1][1],刪後面一條路徑。那麼此時多一個for循環。
2、樣例代碼,請參考:圖的知識點補充(AOE網絡的關鍵路徑)