Kruskal算法
Kruskal算法的时间复杂度为O(ElogE)E为边数
Kruskal算法是基于贪心的思想得到的。
首先我们把所有的边按照权值先从小到大排列,接着按照顺序选取每条边,
如果这条边的两个端点不属于同一集合,那么就将它们合并,直到所有的点都属于同一个集合为止。
至于怎么合并到一个集合,那么这里我们就可以用到一个工具——-并查集
换而言之,Kruskal算法就是基于并查集的贪心算法
即:
输入: 图G
输出: 图G的最小生成树
具体流程:
(1)将图G看做一个森林,每个顶点为一棵独立的树
(2)将所有的边加入集合S,即一开始S = E
(3)从S中拿出一条最短的边(u,v),如果(u,v)不在同一棵树内,则连接u,v合并这两棵树,同时将(u,v)加入生成树的边集E’
(4)重复(3)直到所有点属于同一棵树,边集E’就是一棵最小生成树
1 int n,m,ans; 2 int f[5005]; 3 struct bian{ 4 int x,y,z; 5 }a[200009]; 6 bool cmp(bian x,bian y){return x.z<y.z;} 7 int F(int x) 8 { 9 if(x!=f[x]) return f[x]=F(f[x]); 10 return x; 11 } 12 int main() 13 { 14 scanf("%d%d",&n,&m); 15 for(int i=1;i<=n;i++)f[i]=i; 16 for(int i=1;i<=m;i++) 17 scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); 18 sort(a+1,a+m+1,cmp); 19 for(int i=1,fx,fy;i<=m;i++) 20 { 21 fx=F(a[i].x);fy=F(a[i].y); 22 if(fx!=fy) 23 { 24 f[fx]=fy; 25 ans+=a[i].z; 26 } 27 } 28 cout<<ans; 29 return 0; 30 }