两种写法
第一种:使用数组
/*
时间复杂度:O(nlogn)
*/
#include<bits/stdc++.h>
using namespace std;
#define MAX 200000+10
int n,m; //n:结点的数量 m:边的数量
int u[MAX],v[MAX],w[MAX],r[MAX],p[MAX]; //u[i]v[i]第i条边的两端点,w[i]第i条边的权值,r[i]第i小的边的序号,p[i]并查集
int cmp(const int i, const int j) { return w[i] < w[j]; } //间接排序函数
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); } //并查集的find
int Kruskal()
{
int ans = 0;
for (int i = 0; i <= n; i++) p[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]; //找出当前边两个端点所在集合编号
int x = find(u[e]);
int y = find(v[e]);
if (x != y) //如果在不同集合,合并
{
ans += w[e];
p[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;
}
/*
洛谷 p3366
输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7
*/
第二种:使用结构体
/*
时间复杂度:O(nlogn)
*/
#include<bits/stdc++.h>
using namespace std;
#define Max 200000+10
struct Edge
{
int v,w,cost;
};
Edge a[Max];
int n,m,ans=0,p[Max];
bool cmp(Edge x,Edge y)
{
return x.cost<y.cost;
}
int find(int x)
{
return x==p[x]?x:p[x]=find(p[x]);
}
void Kruskal()
{
for(int i=0;i<=n;i++) p[i]=i; //初始化并查集
sort(a,a+m,cmp); //按照边的大小排序
int k=0,z=0; //k为已经选择的边数,z为当前选择的边
ans=0;
while(k!=n-1) //选择出n-1条边,即为最小生成树
{
int x=find(a[z].v);
int y=find(a[z].w);
if(x!=y)
{
p[x]=y; //合并并查集
ans+=a[z].cost;
k++;
}
z++;
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>a[i].v>>a[i].w>>a[i].cost;
}
Kruskal();
cout<<ans<<endl;
return 0;
}
/*
洛谷 p3366
输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7
*/