最小生成樹兩連

2022-09-17 13:33:20 字數 1834 閱讀 4132

並查集優化的克魯斯卡爾演算法和優先佇列+鏈式前向星優化的普利姆演算法

kruskal是常用的最小生成樹演算法,演算法利用貪心思想,每次選擇沒用過且不構成環的邊的最小邊,直到選擇了n-1條邊,通常我們用並查集這個資料結構去優化,優化後的kruskal演算法複雜度是\(o(mlogm+m\alpha m)\),複雜度只和邊的數量有關,所以適用於稀疏圖

#include using namespace std;

int n; // n個點

int m; // m條邊

int ans; //最小生成樹的權值

const int maxm = 2e5 + 5; //邊的資料範圍

const int maxn = 5005; //點的資料範圍

struct node e[maxm];

bool cmp(node a, node b)

int parent[maxn];

int rnk[maxn];

void init()

}int find(int x) else

}void unite(int x, int y)

if (rnk[x] < rnk[y]) else

}}bool issame(int x, int y)

void kruskal(void)

if (cnt == n - 1)

}}int main(void)

sort(e + 1, e + m + 1, cmp); //按照邊的權值排序

init();

kruskal();

printf("%d\n", ans);

return 0;

}

prim是針對點的最小生成樹演算法,任意選乙個點出發,構成乙個集合v,然後每次選擇距離這個集合最近的點加入,當所有點都被加入集合v中時得到這棵樹。使用優先佇列和鏈式前向星優化的prim演算法的時間複雜度是\(o((m+n)logm)\),適用於稠密圖

#include using namespace std;

int n; // n個點

int m; // m條邊

int ans; //最小生成樹的權值

int cnt; //邊的index

const int maxm = 2e5 + 5; //邊的資料範圍

const int maxn = 5005; //點的資料範圍

struct node

} e[maxm << 1]; //無向圖開兩倍邊

int head[maxn]; // head[i]表示最後出現的以i為起點的邊

bool vis[maxn]; //訪問過了的點

void add(int u, int v, int w)

priority_queueq;

void init()

void prim()

}node t = q.top(); //從當前的可拓展邊中找出一條最短的

q.pop();

while (vis[t.to])

now = t.to;

ans += t.w;

}}int main(void)

prim();

printf("%d\n", ans);

return 0;

}

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...

最小生成樹

package 圖 最小生成樹是用最少的邊吧把所有的節點連線起來。於是和圖的深度優先搜素差不多。class stack public void push int key public int pop 檢視棧頂的元素 public int peek public boolean isempty cla...

最小生成樹

define max vertex num 20 最大頂點數 typedef int adjmatrix max vertex num max vertex num 鄰接矩陣型別 typedef char vertextype typedef struct mgraph struct dnodecl...