- 并查集维护最小生成树的形成。
- 按边权大小排序,然后枚举每一条边。
struct edge{//起点u,终点v,权值w
int u,v,w;
}e[100005];
bool cmp(edge a,edge b){
return a.w<b.w;
}
int a[100005],k,ans;//k用来维护当前生成树的边数,ans为最小生成树的权值和
int find(int x){
return x==a[x]?x:a[x]=find(a[x]);
}
bool kruskal()
{
sort(e+1,e+m+1,cmp);//将所有边的权值从小到大排序
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v,w=e[i].w;
if(find(u)!=find(v))
{
a[find(u)]=a[find(v)];
k++;
ans+=w;
}
if(k==n-1)
return true;
}
return false;//原图是森林,不存在全图的最小生成树
}
正确性证明:假设图中权值最小的一条边没有被构入生成树中,此时必然可以断开原树中的某一条边将这条边纳入生成树,然后缩点(最小权值边所连接的两点看成一点),此时又回到了第一步,由此可证得当前未被使用的最小权值边(非缩点后的等价自环)应被替换进生成树中 。