图论算法——Kruskal算法
2017-06-27 22:00
155 查看
Kruskal 算法是针对最小生成树的一个算法,不优化的时间复杂度是O(e^2),用并查集优化的时间复杂度就是O(eloge)其中e为边数。
所以就可以看出,并查集对Kruskal的优化还是很大的。
我们先来看看Kruskal针对的到底是一个什么样的问题:
•输入一个有权无向连通图G,在已有的边中删掉尽可能多的边得到一个新的图G’。使得G’依旧是连通图并且剩余的边权值之和最小,请输出G’中所有边权之和。
所以说,最小生成树虽然是“树”,但这却是一个有关图论的问题。
Q:树怎么能跟图扯到一起呢?
A:树其实就是一个特殊的图,也就是树是一个没有环的图
Q:但问题中并没有提到“没有环”啊?
A:这就是问题的关键所在。
我们先来回答几个问题:
Q:问题中的Q’里不能有什么?
A:不能有环!
Q:为什么不能有环?
A:因为在一个在Q’中所有的环里的很多边都是多余的,为什么这么说么?看看下面这张图就知道了!
你看出什么了吗?这就是之前那个问题的答案!在Q’中是肯定不能有环的!有环也可以拆掉,只要保持联通就可以了。没有环的图就是什么?树!
解决了这些疑惑,就可以开始Kruskal算法了,Kruskal算法的步骤是:
1、 将G中所有点之间的边断开得到G’,然后将所有边按照权值从小到大排序不妨记为边集E。
2、 集合E中当前权值最小的边记为e,将e从E中删除。
3、 如果e连接的顶点v和u在G’中已经连通,转2。
这一点也就是并查集所能优化的一点,并查集可以判断这两个节点是否已经联通,如果你不知道并查集怎么用,有请戳并查集帮助1(戳我)或并查集帮助2(戳我)。
4、 将e,加入G’
5、 如果G’中边的数量等于n-1,算法结束,否则转2。
详见代码:
如果代码有问题,欢迎留言!
这里有几个初学者不会很知道的东西,给出几个帮助:
vector:vector帮助1(戳我),vector帮助2(戳我)。
sort:sort帮助1(戳我)
operator:帮助1
所以就可以看出,并查集对Kruskal的优化还是很大的。
我们先来看看Kruskal针对的到底是一个什么样的问题:
•输入一个有权无向连通图G,在已有的边中删掉尽可能多的边得到一个新的图G’。使得G’依旧是连通图并且剩余的边权值之和最小,请输出G’中所有边权之和。
所以说,最小生成树虽然是“树”,但这却是一个有关图论的问题。
Q:树怎么能跟图扯到一起呢?
A:树其实就是一个特殊的图,也就是树是一个没有环的图
Q:但问题中并没有提到“没有环”啊?
A:这就是问题的关键所在。
我们先来回答几个问题:
Q:问题中的Q’里不能有什么?
A:不能有环!
Q:为什么不能有环?
A:因为在一个在Q’中所有的环里的很多边都是多余的,为什么这么说么?看看下面这张图就知道了!
你看出什么了吗?这就是之前那个问题的答案!在Q’中是肯定不能有环的!有环也可以拆掉,只要保持联通就可以了。没有环的图就是什么?树!
解决了这些疑惑,就可以开始Kruskal算法了,Kruskal算法的步骤是:
1、 将G中所有点之间的边断开得到G’,然后将所有边按照权值从小到大排序不妨记为边集E。
2、 集合E中当前权值最小的边记为e,将e从E中删除。
3、 如果e连接的顶点v和u在G’中已经连通,转2。
这一点也就是并查集所能优化的一点,并查集可以判断这两个节点是否已经联通,如果你不知道并查集怎么用,有请戳并查集帮助1(戳我)或并查集帮助2(戳我)。
4、 将e,加入G’
5、 如果G’中边的数量等于n-1,算法结束,否则转2。
详见代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<vector> class edge { public: int u; int v; int weight; }; bool operator< (const edge& a,const edge& b) { return a.weight<b.weight; } std::vector<edge> edges; int father[1001]; int get_father(int x) { if(father[x]==x)return x; return father[x] = get_father(father[x]); } int main() { int n,m; std::cin>>n>>m; edges.resize(m+1); for(int i = 0;i<m;i++) std::cin>>edges[i].u>>edges[i].v>>edges[i].weight; std::sort(edges.begin(),edges.end()); for(int i = 0;i<n;i++)father[i] = i; int ans = 0; for(int i = 0;i<m;i++) { if(get_father(edges[i].u)==get_father(edges[i].v))continue; ans += edges[i].weight; father[get_father(edges[i].u)] = father[get_father(edges[i].v)]; } std::cout<<ans; return 0; }
如果代码有问题,欢迎留言!
这里有几个初学者不会很知道的东西,给出几个帮助:
vector:vector帮助1(戳我),vector帮助2(戳我)。
sort:sort帮助1(戳我)
operator:帮助1
相关文章推荐
- 算法_图论-Kruskal算法
- [算法与数据结构] - No.9 图论(2)- 最小生成树Prim算法与Kruskal算法
- 紫书第十一章-----图论模型与算法(最小生成树prim算法和kruskal算法)
- 图论中最小生成树构造算法之Prim算法和Kruskal算法
- 图论——寻找无向连通图割点算法
- 算法-图论_关键节点的判断
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- 最小生成树(prime算法、kruskal算法) 和 最短路径算法(floyd、dijkstra)
- POJ 2387 Til the Cows Come Home(图论几个基本算法的初探)
- 算法分析与设计第三周习题:图论算法之310. Minimum Height Trees
- 【索引】算法竞赛入门经典-第11章 图论模型与算法
- 算法笔记_149:图论之桥的应用(Java)
- 算法笔记_150:图论之双连通及桥的应用(Java)
- 【NOIp复习】图论基础算法
- 图论,匈牙利算法
- 图论の最短路径算法
- Prime算法 与 Kruskal算法的时间复杂度比较
- 2018年全国多校算法寒假训练营练习比赛(第四场)(图论)
- 图算法总结----Kruskal算法
- 【图论】【二分图匹配】匈牙利算法正确性证明所需的两个定理证明