prim和kruskal比较
推荐:http://squirrelrao.iteye.com/blog/1044867
http://www.cnblogs.com/xwdreamer/archive/2011/06/16/2296997.html
http://blog.csdn.net/believejava/article/details/17414037
一、Prim算法:
Prim算法实现的是找出一个有权重连通图中的最小生成树,即:具有最小权重且连接到所有结点的树。(强调的是树,树是没有回路的)。
Prim算法是这样来做的:
首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中。加入之后如果产生回路则跳过这条边,选择下一个结点。当所有结点都加入到最小生成树中之后,就找出了连通图中的最小生成树了。
/*
prim 最小生成树算法
过程:prim算法将图分为两部分,假设原顶点集为V,将其分为S和V-S两部分,S为已经确定在最小生成树上的顶点,
开始时,将任意一个顶点加入到S,然后每次在V-S中寻找距离S中的点最近的点。作为下一个加入最小生成树上的点。
所有N个节点都加入到最小生成树中时,最小生成树构造完毕。 实现:对于邻接矩阵构造的图,可以用low[N]保存每个顶点到已加入生成树中所有点的最小距离。
每次寻找这个距离最小的一个点加入最小生成树中。再根据这个点的距离更新其它未加入生成树中的点。
直到所有的点都加入到最小生成树中。
*/ // Eg:HDU 1102 #include <stdio.h>
#include <string.h>
#include <iostream>
#define inf 1000000
using namespace std; int g[210][210];
int low[210];
int vis[210]; // 表示该点是否已经加入最小生成树中
int n; int prim() {
for (int i=0; i<n; ++i) {
low[i] = g[0][i];
} int ans = 0;
memset(vis, 0, sizeof(vis));
vis[0] = 1; for (int i=1; i<n; ++i) { // 循环n-1次,找剩下的n-1个点。
int k = -1, mindis = inf;
for (int j=0; j<n; ++j) { // 循环找当前剩下的点中 距离最小生成树点集距离最短的点。
if (!vis[j] && low[j] < mindis) {
mindis = low[j];
k = j;
}
} if (k == -1) return -1;
vis[k] = 1; // 加入最小生成树点集
ans += mindis; for (int j=0; j<n; ++j) { // 更新没加入最小生成树的点中 距离是否会缩短。
/*if (!vis[j] && low[j] > low[k] + g[k][j]) {
low[j] = low[k] + g[k][j];
}*/ if (!vis[j] && low[j] > g[k][j]) { // 上面的if是错的。low数组存储的距离是当前点到生成树中所有点距离最小的的点。
low[j] = g[k][j]; // 因为这个点加入最小生成树集合中,可以和其中任意一个点连一条边。
}
}
}
return ans;
} int main() {
int q;
while(cin >> n) {
for (int i=0; i<n; ++i) {
for (int j=0; j<n; ++j) {
cin >> g[i][j];
}
} cin >> q;
for (int i=0; i<q; ++i) {
int a, b;
cin >> a >> b;
a--, b--;
g[a][b] = 0;
g[b][a] = 0;
} int ans = prim();
cout << ans << endl;
}
return 0;
}
二、Kruskal算法:
Kruskal算法与Prim算法的不同之处在于,Kruskal在找最小生成树结点之前,需要对所有权重边做从小到大排序。将排序好的权重边依次加入到最小生成树中,如果加入时产生回路就跳过这条边,加入下一条边。当所有结点都加入到最小生成树中之后,就找出了最小生成树。
无疑,Kruskal算法在效率上要比Prim算法快,因为Kruskal只需要对权重边做一次排序,而Prim算法则需要做多次排序。尽管Prim算法每次做的算法涉及的权重边不一定会涵盖连通图中的所有边,但是随着所使用的排序算法的效率的提高,Kruskal算法和Prim算法之间的差异将会清晰的显性出来。
/*
最小生成树 kruskal算法
过程:每次选取没有参与构造最小生成树并且加入之后不会构成回路的边中权值最小的一条
作为最小生成树的一条新边。直至选择了V-1条边。
*/ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define maxn 2100
using namespace std; int fa[maxn], r[maxn]; void init(int n) {
for (int i=1; i<=n; ++i) {
fa[i] = i;
r[i] = 1;
}
} int find_fa(int v) { // 递归式路径压缩
if (fa[v] != v) fa[v] = find_fa(fa[v]);
return fa[v];
} /*int find_fa(int v) { // 非递归式路径压缩
int k, j, r;
r = v;
while(r != fa[r])
r = fa[r]; //找到根节点 记录在r上。
k = v;
while(k != r) {
j = fa[k];
fa[k] = r;
k = j;
}
return r;
}*/ /*void unin(int u, int v) { // 非按秩合并
int fau = find_fa(u);
int fav = find_fa(v);
if (fau != fav)
fa[fav] = fau;
}*/ void unin(int u, int v) { // 按秩合并
int fau = find_fa(u);
int fav = find_fa(v);
if (fau == fav) return; if (r[u] < r[v]) fa[fau] = fav;
else {
if (r[u] == r[v])
r[u]++;
fa[fav] = fau;
}
} struct Edge {
int u, v, w;
}edge[1000010]; bool cmp(Edge a, Edge b) {
return a.w > b.w;
} int ans;
int kruskal(int n, int m) { // 传入顶点个数n 和 边的个数m
init(n);
sort(edge, edge+m, cmp);
ans = 0;
int ret = 0; // 生成树的总权值
int cnt = 0; // 已加入最小生成树的边的数量 for (int i=0; i<m; ++i) {
if (find_fa(1) == find_fa(n)) return -1;
int u = edge[i].u;
int v = edge[i].v;
if (find_fa(u) != find_fa(v)) {
cnt++;
ret += edge[i].w;
unin(u, v);
ans = edge[i].w;
}
if (cnt == n-1) return ret; // 已找到n-1条边,生成树构造完毕
}
return -1;
} int main() {
int casee = 1;
int t;
cin >> t;
while(t--) {
int n, m;
cin >> n >> m;
for (int i=0; i<m; ++i) {
cin >> edge[i].u >> edge[i].v >> edge[i].w;
}
kruskal(n, m);
cout << "Scenario #" << casee++ << ":" << endl << ans << endl << endl;
}
return 0;
}
关于时间复杂度:
prim:该算法的时间复杂度为O(n2)。与图中边数无关,该算法适合于稠密图。
kruskal:需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。适合稀疏图。
prim和kruskal比较的更多相关文章
- Prim和Kruskal最小生成树
标题: Prim和Kruskal最小生成树时 限: 2000 ms内存限制: 15000 K总时限: 3000 ms描述: 给出一个矩阵,要求以矩阵方式单步输出生成过程.要求先输出Prim生成过程,再 ...
- 【图论】信手拈来的Prim,Kruskal和Dijkstra
关于三个简单的图论算法 prim,dijkstra和kruskal三个图论的算法,初学者容易将他们搞混,所以放在一起了. prim和kruskal是最小生成树(MST)的算法,dijkstra是单源最 ...
- 图的最小生成树的理解和实现:Prim和Kruskal算法
最小生成树 一个连通图的生成树是一个极小的连通子图,它含有图中所有的顶点,但只有足以构成一棵树的n-1条边.我们将构造连通网的最小代价生成树称为最小生成树(Minimum Cost Spanning ...
- 最小生成树(prim和kruskal)
最小生成树(prim和kruskal) 最小生成树的最优子结构性质 设一个最小生成树是T.如果选出一个T中的一条边,分裂成的两个树T1,T2依然是它们的点集组成的最小生成树.这可以用反证法来证.反着来 ...
- HDU 3080 The plan of city rebuild(prim和kruskal)
The plan of city rebuild Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...
- 最小生成树,Prim和Kruskal的原理与实现
文章首先于微信公众号:小K算法,关注第一时间获取更新信息 1 新农村建设 大清都亡了,我们村还没有通网.为了响应国家的新农村建设的号召,村里也开始了网络工程的建设. 穷乡僻壤,人烟稀少,如何布局网线, ...
- 最小生成树MST算法(Prim、Kruskal)
最小生成树MST(Minimum Spanning Tree) (1)概念 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边,所谓一个 ...
- Prim和Kruskal求最小生成树
Prim: 算法步骤: 1.任意结点开始(不妨设为v1)构造最小生成树: 2.首先把这个结点(出发点)包括进生成树里, 3.然后在那些其一个端点已在生成树里.另一端点还未在生成树里的所有边中找出权最小 ...
- hdu_1875_畅通工程再续 prim和kruskal
这个题是个典型的最小生成树的题目,但是刚开始怎么都过不了,后来发现两种写法都有疏忽,但是prim的到目前为止不懂为什么刚开始的不对,kruskal算法,并查集的初始条件从0开始写成从1开始了,所以已知 ...
- 图的最小生成树(Prim、Kruskal)
理论: Prim: 基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合.算法从U={u0}(u0∈V).TE={}开始.重复执行下列操作: 在所有u∈U,v∈V-U的边(u,v)∈E ...
随机推荐
- Python并行编程(十四):异步编程
1.基本概念 除了顺序执行和并行执行的模型以外,还有异步模型,这是事件驱动模型的基础.异步活动的执行模型可以只有一个单一的主控制流,能在单核心系统和多核心系统中运行. 在并发执行的异步模型中,许多任务 ...
- EOS Dapp开发(1)-基于Docker的开发环境搭建
随着EOS主网的上线,相信基于EOS的Dapp开发会越来越多,查阅了很多资料相关的开发资料都不是很多,只能自己摸索,按照网上仅有的几篇教程,先git clonehttps://github.com/E ...
- linux 如何查看防火墙是否开启
service iptables status可以查看到iptables服务的当前状态.但是即使服务运行了,防火墙也不一定起作用,你还得看防火墙规则的设置 iptables -L在此说一下关于启动和关 ...
- Hello 2019 Solution
A. Gennady and a Card Game 签到. #include <bits/stdc++.h> using namespace std; ], t[]; bool solv ...
- cocos2dx 3.x 蒙板 遮罩 点击圆功能
//注册触摸 EventListenerTouchOneByOne *listener = EventListenerTouchOneByOne::create(); listener->onT ...
- python: 随机选择
想从一个序列中随机抽取若干元素,或者想生成几个随机数. random 模块有大量的函数用来产生随机数和随机选择元素.比如,要想从一个序列中随机的抽取一个元素,可以使用random.choice() : ...
- Android ActionBar自定义
关于自定义的ActionBar的实现过程,这里做下笔记以供之后查看. 1.默认状态 使用Android Studio新建一个名为“ActionBar”的应用,默认actionbar如图(1)所示. 图 ...
- ubuntu14.04 安装mono
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831 ...
- bzoj1619 / P2919 [USACO08NOV]守护农场Guarding the Farm
P2919 [USACO08NOV]守护农场Guarding the Farm 相似题:P3456 [POI2007]GRZ-Ridges and Valleys 按海拔是否相同分块 每次bfs海拔相 ...
- 《Java程序设计》第三章-基础语法
20145221<Java程序设计>第三章-基础语法 总结 教材学习内容总结 类型.变量与运算符 类型 Java可区分为基本类型(Primitive Type)和类类型(Class Typ ...