题目:
输入顶点数目,边的数目,输入每条边的两个顶点编号还有每条边的权值,求最小生成树,输出最小生成树的权值。。
注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。
kruskal----归并边;prim----归并点
方法一:kruskal,克鲁斯卡尔,并查集实现。
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1000;
int n, m;
int u[MAXN], v[MAXN], w[MAXN], r[MAXN], fa[MAXN];
int ans = 0;
//假设第i条边的两个端点序号和权值分别保存在u[i], v[i]和w[i]中。
//而排序后第i小的边的序号保存在r[i]中。
bool cmp(int i, int j) { //间接排序!
return w[i] < w[j];
}
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]); //把遍历过的节点都改成树根的儿子,提高后续查找的速度。
}
int kruskal() {
int ans = 0;
for(int i = 0; i < n; ++i) fa[i] = i; //初始化并查集,让每一个点自成一个连通分量。
for(int i = 0; i < m; ++i) r[i] = i; //初始化边序号。
sort(r, r+m, cmp); //间接排序!
for(int i = 0; i < m; ++i) {
int e = r[i]; //e代表边的序号!
int x = find(u[e]), y = find(v[e]); //找出这条边的两个顶点所在的集合的代表元
if(x != y) { //如果这两个点不在同一个连通分量
ans += w[e]; //把这条边加入到MST中
fa[x] = y; //合并两个集合!
}
}
return ans;
}
int main() {
cin >> n >> m;
for(int i = 0; i < m; ++i) {
cin >> u[i] >> v[i] >> w[i];
}
cout << kruskal() << endl;
return 0;
}
方法二:prim,普里姆,实现。