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,這時候你需要判斷能不能用這條邊,因為最小生成樹是不能形成迴路,所以用到了...