版权声明:转载请保留原地址 https://blog.csdn.net/u012972031/article/details/83591454
Kruskal的用处:
- 得出一个图的一个最小生成树(最小生成树就是一个图中总权值最小的一个子树)
Kruskal的思想:
- 由于要获得最小生成树,而最小生成树一定连接了所有结点,所以边权最小的边一定会被选择(这个需要自己证明)
- 然后,我们将边权最小的边进行缩点,缩点的方法是使用并查集,也就是把互相连接的点放到同一个集合。
- 然后重复第一个步骤。当已选择的边的数量等于点的总数减一时,则最小生成树已创建完成。
Kruskal的具体实现:
- 获取边权最小的边可以使用sort函数,也可以使用优先队列
- 缩点可以使用并查集
例题:https://www.luogu.org/problemnew/show/P3366
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int ans=0,cnt=0,n,m,fa[200005];
struct Edge{
int u,v,w;
}e[200005];
int cmp(Edge a,Edge b){
return a.w<b.w;
}
void addEdge(int u,int v,int w){
e[++cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
}
int find(int a){
while(a!=fa[a]){
a=fa[a]=fa[fa[a]];
}
return a;
}
void kruskal(){
int eu,ev;
int sum=0;
for(int i=1;i<=m;i++){
eu=find(e[i].u),ev=find(e[i].v);
if(eu==ev)continue;
sum++;
fa[eu]=ev;
ans+=e[i].w;
if(sum==n-1)return;
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=1;i<=m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c);
}
sort(e,e+m,cmp);
kruskal();
printf("%d\n",ans);
return 0;
}
欢迎加入我们的OI讨论群
群号:849352599