一、kruskal算法(利用并查集)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,tot=0,k=0;//n端点总数,m边数,tot记录最终答案,k已经连接了多少边
int fat[200010];//记录集体老大
struct node
{
int from,to,dis;//结构体储存边
}edge[200010];
bool cmp(const node &a,const node &b)//sort排序(当然你也可以快排)
{
return a.dis<b.dis;
}
int father(int x)//找集体老大,并查集的一部分
{
if(fat[x]!=x)
return father(fat[x]);
else return x;
}
void unionn(int x,int y)//加入团体,并查集的一部分
{
fat[father(y)]=father(x);
}
int main()
{
scanf("%d%d",&n,&m);//输入点数,边数
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].dis);//输入边的信息
}
for(int i=1;i<=n;i++) fat[i]=i;//自己最开始就是自己的老大 (初始化)
sort(edge+1,edge+1+m,cmp);//按权值排序(kruskal的体现)
for(int i=1;i<=m;i++)//从小到大遍历
{
if(k==n-1) break;//n个点需要n-1条边连接
if(father(edge[i].from)!=father(edge[i].to))//假如不在一个团体
{
unionn(edge[i].from,edge[i].to);//加入
tot+=edge[i].dis;//记录边权
k++;//已连接边数+1
}
}
printf("%d",tot);
return 0;
}
二、prim算法
#include<bits/stdc++.h>
const int maxn = 1e6 + 1;
inline int read() //快读入数据
{
register int x = 0, ch = getchar(), f = 1;
while(!isdigit(ch)){if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
return x * f;
}
int n, m;
struct node{
int u;
int v;
int w;
}e[maxn];
int fa[maxn], cnt, sum, num;
void add(int x, int y, int w)
{
e[++ cnt].u = x;
e[cnt].v = y;
e[cnt].w = w;
}
bool cmp(node x, node y)
{
return x.w < y.w;
}
int find(int x)
{
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);//路径压缩
}
/*
int find(int x)
{
if(fa[x] == x) return x;
else
{
fa[x] = find(fa[x]);//路径压缩
return fa[x];
}
}
*/
void kruskal()
{
for(int i = 1; i <= cnt; i ++)
{
int x = find(e[i].u);
int y = find(e[i].v);
if(x == y) continue;
fa[x] = y;
sum += e[i].w;
if(++ num == n - 1) break;//如果构成了一颗树
}
}
int main()
{
n = read();
m = read();
for(int i = 1; i <= n; i ++) fa[i] = i;
while(m --)
{
int x, y, w;
x = read();
y = read();
w = read();
add(x, y, w);
}
std:: sort(e + 1, e + 1 + cnt, cmp);
kruskal();
printf("%d",sum);
return 0;
}