最小生成树,走向图论带师的第一步(OWO)=!
想来本蒟蒻在寒假集训时看到树,图就瑟瑟发抖,更别说最小生成树这个逼格满满的名字
当初的我看到长长的代码就萌生退意
但当我最近再看的时候,突然就顿悟了的说 耶
As we all know 最小生成树最常用的两个算法,Kruskal算法和Prim算法
Kruskal对边排序,所以适合稀疏图,prim对点操作,所以适合稠密图
其中,Kruskal算法是最常用的,因为比较好实现代码而且时间复杂度更小(O(nlog(n)))
Kruskal算法的思路就是将所有的边排序,然后按排好的顺序来遍历
如果两点尚未连接,则更新ans(连接与否用并查集来check)
如果连接了,就跳过
满足条件后break掉就行了
#include<bits/stdc++.h>
using namespace std;
struct node
{
int b;///起始节点
int to;///到达的节点
int l;///两节点之间长度
} a[200005];
int ans=0;
int fa[5005];///并查集的father数组
int fin(int x)///并查集查找祖先函数(路径压缩)
{
if(x==fa[x])
return x;
else return fa[x]=fin(fa[x]);
}
int cmp(node a,node b)///自定义排序函数
{
return a.l<b.l;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) fa[i]=i;
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[i].b=x,a[i].to=y,a[i].l=z;
}
int cnt=0;
sort(a+1,a+m+1,cmp);
for(int i=1; i<=m; i++)
{
int aa=fin(a[i].b);
int bb=fin(a[i].to);
if(aa!=bb)
{
ans+=a[i].l;
fa[bb]=aa;
if(++cnt==n-1) break;
}
}
printf("%d\n",ans);
return 0;
}
挖坑。。。。。