次小生成樹 prim和kruskal

2021-08-07 17:27:03 字數 1790 閱讀 6642

prim:

先用prim求出最小生成樹t,在prim的同時,用乙個矩陣maxd[u][v] 記錄 在t中鏈結任意兩點u,v的唯一的路中權值最大的那條邊的權值,這是很容易做到的,因為prim是每次增加乙個結點s, 在此需要儲存節點和其父節點,採用dp,則最大權值要麼是新加入的邊,要麼是父節點到起始點的採用dp算出來的距離。即:

maxd[j][p] = max[p][j] = lowc[p] > max[j][closest[p]] ? lowc[p] : max[j][closest[p]] ;

列舉所有不在t中的邊uv, 加入邊uv則必然替換權為maxd[u][v]的邊,這樣才能保證次小。

const int inf=0x3f3f3f3f;

const int maxn=110;

bool vis[maxn],used[maxn][maxn];

int lowc[maxn],closest[maxn],maxd[maxn][maxn];

int prim(int cost[maxn],int n)//點是0~n-1

for(int i=1; i

if(minc==inf)return -1;//原圖不連通

ans+=minc;

vis[p]=true;//p點已訪問

used[p][closest[p]]=used[closest[p]][p]=true;

for(int j=0; j

if(!vis[j]&&lowc[j]>cost[p][j])}}

return ans;

}

還有一步列舉,這裡就不寫了。

kruskal:

多次求最小樹: 首先,用kruskal求得最小生成樹,並用visit陣列記錄最小生成樹的邊,假設為總共num條 然後,迴圈求最小生成樹num次,每次都不用第一次求得的最小生成樹的邊

假設:第一次求最小生成樹用到了 1、2、4這三條邊,總共5條邊,那迴圈3次的時候,每次分別不用1、2、4求得最小生成樹的mst,最小的mst即為次小生成樹。

#include

#include

#include

#include

using

namespace

std;

#define m 99999999

int n, m,w;

int f[10005], sum, cou;

int visit[10005];

struct edge

;edge e[10005];

void init()

}int cmp(edge a, edge b)

}int merg(int v, int u)

return0;}

int mintree()

if (cou == n - 1)

}//cout << sum << endl;

return flag ;

}///重點

int cimintree()

if (cou == n - 1)}}

if (flag&&sum < min) min = sum;

}min = (min == m) ? -1 : min;

return min;

}int main()

sort(e + 1, e + m + 1, cmp);

flag = mintree();

if (flag == 0)

else

}return

0;}

次小生成樹(Prim)

這裡的思路就是先用prim演算法求的最小生成樹,然後在prim演算法中新增乙個max陣列,用max陣列存放兩點間的最大距離,並且用乙個use陣列 布林型別 存放是否使用過該邊,最後再在沒有使用的變進行遍歷,找出最小,求的最小生成樹!下面介紹一下利用prim求次小生成樹的主要步驟。1.先求出來最小生成...

次小生成樹 Prim

我們最常見的是最小生成樹,我們最長使用的是prim和kruskal演算法,乙個是對點進行處理,乙個是對邊進行處理,對於次小生成樹來說我們同樣可以使用這兩個方法進行處理,這裡我們先以prim的寫法為例。首先我們要清楚的是什麼是最小生成樹 乙個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原...

Algorithm 最小生成樹之 Kruskal

個人觀點,較prime演算法,kurskal演算法更加的簡單,這裡我們只需要每一次去需找權值最小的那條邊就好,在這裡我們先可以利用sort進行快排,得到權值最小的map i 得到該條邊的兩個節點map i u 和map i v,這時候你需要判斷能不能用這條邊,因為最小生成樹是不能形成迴路,所以用到了...