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条边输出错误 }
来源:https://www.cnblogs.com/zhaoxuelin/p/12659418.html