最小生成樹演算法總結 Kruskal,Prim

2021-10-19 09:04:47 字數 2093 閱讀 9667

今天覆習最小生成樹演算法。

最小生成樹指的是在乙個圖中選擇n-1條邊將所有n個頂點連起來,且n-1條邊的權值之和最小。形象一點說就是找出一條路線遍歷完所有點,不能形成迴路且總路程最短。

kurskal演算法的核心思想是將邊按權值排序,每次選出權值最小的邊,只要不會形成迴路就加入結果集,如果形成了迴路就不選這條邊,類似於貪心的思想。

具體做法是先將邊按權值公升序排序然後依次遍歷,判斷是否形成迴路的方法是將點劃分不同集合,初始狀態每個點為乙個集合,只有當一條邊的兩端分別位於兩個集合時才選擇這條邊,否則就丟棄,這裡用到了並查集來處理集合關係,可以參考這篇博文:選擇一條邊之後要將兩個點合併到同一集合。

模板題:

**如下,還是比較好理解的,時間複雜度為\(o(mlogm)\)。

#include #include using namespace std;

int n, m;

int pre[5005];

int find(int x)

struct line

}arr[200005];

int kruskal()

} return cnt == 1 ? res : -1;//如果cnt不等於1說明沒找到n-1條邊,無最小生成樹

}int main()

kruskal演算法是選擇邊的思路,而prim演算法通過選擇點來得到最小生成樹,有點類似於dijkstra的感覺,初始源點可以任意選擇,把點劃分成已選擇的點和未選擇的點兩個集合,需要維護乙個dis陣列代表每個點到已選擇點的最短距離,不斷把dis最小的未選擇點加入已選擇點集合然後更新dis,當所有點都變成已選擇點(dis==0)的時候就得到了最小生成樹。

**如下,真的是跟dijkstra很像了。

#include #include using namespace std;

#define inf 2000000000

int n, m;

int dis[5005];

int total = 0;

int head[5005], val[400005], to[400005], nextl[400005];

void addline(int a, int b, int c)

int prim()

} if (min == inf && u != 1)return -1;//如果遍歷之後未選擇點dis都為inf,說明該圖是非連通圖

res += dis[u];

dis[u] = 0;

for (int j = head[u]; j; j = nextl[j])//更新該點周圍的dis

}return res;

}int main()

int res = prim();

if (-1 == res)cout << "orz"; else cout << res;

return 0;

}

既然prim也是要每次取dis最小的點,當然也和dijkstra一樣可以用堆優化,樸素的prim時間複雜度為\(o(n^2)\),優化後達到\(o(nlogn)\),**如下:

#include #include #include using namespace std;

#define inf 2000000000

int n, m;

int dis[5005];

int total = 0;

int head[5005], val[400005], to[400005], nextl[400005];

bool mark[5005];

void addline(int a, int b, int c)

typedef pairp;

priority_queue, greater> q;

int prim()

} }return res;

}int main()

int res = prim();

if (-1 == res)cout << "orz"; else cout << res;

return 0;

}

所以選擇使用哪個演算法就看是點多還是邊多了。

最小生成樹演算法 Prim演算法和Kruskal演算法

prim演算法理解,可以看這篇文章 其實就是每次從當前樹中外選取乙個離樹最近且不構成環的點,同時sum記錄權值,然後把這個點加入樹中,直到所有節點都被訪問過,最小生成樹生成成功,輸出最小生成樹的權值和。下面是prim演算法的板子,和最短路有點相似,也稱為 加點法 最小生成樹prim演算法 inclu...

最小生成樹演算法總結

首先,最小生成樹是建立在無向圖中的,對於乙個有n個點的圖,最少需要n 1條邊使得這n個點進行連通,由這n 1條邊組成的子圖稱為原圖的生成樹,乙個圖的生成樹並不是唯一的。最小生成樹則是樹中權值之和最小的一顆生成樹,最小生成樹也可能不唯一。最小生成樹一般有兩種演算法,一種是prim演算法,另一種是kru...

soj 3366 複習最小生成樹kruskal

題目大意 要建井,每個地方都要有,可以選擇直接在這裡挖井,也可以選擇從其他地方已經有井的地方建一條路到這個地方來。有一段時間沒有寫過最小生成樹了,感覺都有一點快要忘記了的感覺。這道題之前沒有過,借鑑了一下別人的思想。發現真的好簡單。而且這種方法在以前使用過,這回居然沒有想出來,要反思一下了。感覺跟之...