最小生成树

≯℡__Kan透↙ 提交于 2020-04-08 14:48:23

1、什么是最小生成树?

我们可以知道一个有n个点n-1条边且无环的无向图一定是一棵树。

最小生成树就是在n个节点的无向图中找到n-1条边构成一棵树且使这棵树的边权和最小。

2、怎么求?

1、Prim算法

这个算法在NOI中不常用(不好用

它的思想与Dijkstra算法相似,这里不再过多介绍

2、Kruskal算法

这才是我们的重点

它的思想是先把每条边按长度从小到大排好(快排)

然后从小到大用并查集的方法把没有"并"到一棵树上并入(在这个过程避免环的出现)

直到加入n-1条边后停止

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; 
int n,m,ans;
struct node{
    int x,y,dis;//结构体定义起点终点边权 
}a[10001];
int fa[10001],cnt;
int Find(int x)
{
    return fa[x]==x?x:fa[x]=Find(fa[x]);
}//查 
bool cmp(node a,node b)
{
    return a.dis<b.dis;
}
int main()
{
  int x,y;
  cin>>n>>m;//输入点数和边数 
  for(int i=1;i<=m;i++)
      cin>>a[i].x>>a[i].y>>a[i].dis;//输入每条边的起点终点边权 
  sort(a+1,a+m+1,cmp);//快排 
  for(int i=1;i<=n;i++)fa[i]=i;//初始化 
  for(int i=1;i<=m&&cnt<n-1;i++)
  {
      x=a[i].x;y=a[i].y;
      if(Find(x)!=Find(y))//判断是否“并”到同一棵树 
      {
          cnt++;//树的边数加一 
            ans+=a[i].dis;//累加边权 
            fa[Find(x)]=Find(y);//“并” 
      } 
  }
  if(cnt==n-1) cout<<ans; //输出 
  else cout<<"error";//不够n-1条边输出错误 
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!