kruskal算法:求最小生成树,给定n个节点,m条边和边的权值,创建一个总权值最小的树
这里用到了并查集的思想:如果要加入的边两个顶点在同一个集合里(代码里即为find(int x)相同),就说明会形成环,这是不行的,否则抓出最小的那条边,放入集合之中,并且标记这条边,下次遍历的时候跳过
到集合总边数为n-1时,不必再寻找,跳出循环。
#include<iostream>
#include<algorithm>
#define maxn 100
using namespace std;
int fa[maxn];
int edge[maxn][maxn];
int vis[maxn];
typedef struct node
{
int to;
int end;
int x;//权值
}node;
node nod[maxn];
void init(int n)
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
}
int find(int x)
{
if(x==fa[x])
return x;
else
return fa[x]=find(fa[x]);
}
void uni(int x,int y)
{
int xnn=find(x);
int ynn=find(y);
if(xnn!=ynn)
fa[xnn]=ynn;
}
int main()
{
int n;//点数
int m;//边数
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>nod[i].to;
cin>>nod[i].end;
cin>>nod[i].x;
}
init(n);
int count=0;
int sum=0;
while(1)
{
int minn=1e9;
int pos=-1;
if(count==n-1)//边数=点数-1,说明已经建立完了一个图;
{
break;
}
//找最小的边
for(int i=1;i<=m;i++)
{
if(vis[i]==0/*这个边没找过*/&&minn>nod[i].x/*找最小边*/&&find(nod[i].to)!=find(nod[i].end)/*两个点不在同一个集合里*/)
{
minn=nod[i].x;
pos=i;
}
}
vis[pos]=1;//说明这个边已经加入了
sum+=nod[pos].x;
uni(nod[pos].to,nod[pos].end);
count++;
}
cout<<sum<<endl;
}
改进:可以先将所有边按权值在开头排序好,就不用一遍一遍找了。代码懒得改了
来源:CSDN
作者:fw鱼鱼
链接:https://blog.csdn.net/weixin_44254608/article/details/104615005