首页 > 代码库 > ACM:最小生成树,kruskal && prim,并查集
ACM:最小生成树,kruskal && prim,并查集
题目:
输入顶点数目,边的数目,输入每条边的两个顶点编号还有每条边的权值,求最小生成树,输出最小生成树的权值。。
注意: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,普里姆,实现。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。