prim演算法:
類似於dij演算法,將每個點距離已經加入的點的集合的最短距離算出,每次取出這些距離裡最短的點加入集合,並在每次加入新的點後更新這些距離即可。
演算法模版:
#define inf 32767;
void prim(mgraph g,int v)}}
}
krustral演算法
先將所有的邊按照邊權值排序,之後利用並查集,檢查邊的兩個點是否被連通,若被連通則忽略,否則加入樹中。
#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;
typedef struct node
e;e edge[100];
int fa[100];
int deep[100];
int n,m;
int sum=0;
void init()
}int find(int x)
void unit(int x,int y) }}
bool same(int x,int y)
void quicksort(int left,int right)
} cout《次小生成樹:
下面介紹一下利用prim求次小生成樹的主要步驟。
1.先求出來最小生成樹。並將最小生成樹任意兩點之間路徑當中的權值最大的那一條找出來,為什麼要找最大的呢,因為生成樹加入一條邊之後一定構成了迴路,那麼肯定要去掉這個迴路當中一條邊才是生成樹,那麼,怎麼去邊才是次小的,那就去掉除了剛剛新增的一條邊之外迴路當中權值最大的乙個,所以留下的就是最小的。
2.列舉最小生成樹外的每一條邊。找出最小的就是次小生成樹。
poj1679 the unique mst
題意:給定圖,讓求它的最小生成樹是否唯一。如果唯一的話輸出最小生成樹的權值和,否則輸出not unique!
思路:直接求次小生成樹就行。
#include #include #include using namespace std;
const int maxn = 111;
const int inf = 0x3f3f3f3f;
int map[maxn][maxn];//鄰接矩陣存圖
int max[maxn][maxn];//表示最小生成樹中i到j的最大邊權
bool used[maxn][maxn];//判斷該邊是否加入最小生成樹
int pre[maxn];
int dis[maxn];
void init(int n)
void read(int m)
}int prim(int n)
pre[1] = 0;
dis[1] = 0;
vis[1] = true;
for (int i = 2; i <= n; i++)
}if (min_dis == inf) return -1;//如果不存在最小生成樹
ans += min_dis;
vis[k] = true;
used[k][pre[k]] = used[pre[k]][k] = true;
for (int j = 1; j <= n; j++)}}
return ans;//最小生成樹的權值之和
}int smst(int n, int min_ans)//min_ans 是最小生成樹的權值和
void solve(int n)
if (smst(n, ans) == ans)
printf("not unique!\n");
else
printf("%d\n", ans);
}
int main()
return 0;
}
最小生成樹與次小生成樹
題意 給出兩個不同方案,每個方案使得所有的城堡被連通 形成連通圖 同時使邊權之和盡量小,問第乙個方案與第二個方案的大小關係。解題思路 因為m個橋能使n個城堡聯通,而兩個大爺的方案中至少存在乙個橋不相同,那麼我們判斷這是乙個求次小生成樹的方法。求次小生成樹模板 列舉 刪邊 再求mst複雜度有點高,看題...
最小生成樹 次小生成樹
一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...
最小生成樹(模版)
如題,給出乙個無向圖,求出最小生成樹,如果該圖不連通,則輸出orz 輸入格式 第一行包含兩個整數n m,表示該圖共有n個結點和m條無向邊。n 5000,m 200000 接下來m行每行包含三個整數xi yi zi,表示有一條長度為zi的無向邊連線結點xi yi 輸出格式 輸出包含乙個數,即最小生成樹...