Kruskal算法
并查集
将每条边从小到大进行排序,从小到大进行选择,如果两个点没连通就把这条边(两个点夹的这个边)连上,并且把两个点设为连通,边数为n-1的时候即为连接完毕.
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn = 5005; //最大顶点数
const int maxm = 200005; //最大边数
int n,m; //n顶点数和m边数
int cnt;
struct edge{
int u,v,w;
bool operator < (const edge a)const{//运算符重载(sort使用)
return w < a.w;
}
}e[maxm];
int fa[maxn]; //father数组
int find(int x){ //并查集查找加压缩
while(x != fa[x])
x = fa[x] = fa[fa[x]];
return x;
}
void kruskal(){ //kruskal算法
int ans = 0;int tot = 0;
for(int i = 1;i <= n;i++)//初始化fa数组
fa[i] = i;
sort(e,e+m); //对边进行排序
for(int i = 0;i < m;i++){
if(find(e[i].u)==find(e[i].v)) //如果u和v在同一颗树中就说明他们已经连通
continue; //跳过
ans += e[i].w; //不是连通的话就写入答案
fa[find(e[i].v)] = find(e[i].u);//把他们合并(将他们连通)
if(++tot<n) //最小生成树边数只有n-1
continue;
}
cout << ans << endl; //最总长度
}
int main()
{
cin >> n >> m;
for(int i = 0;i < m;i++)
cin >> e[i].u >> e[i].v >> e[i].w;
kruskal();
return 0;
}