首页 > 代码库 > 最小生成树

最小生成树

Kruskal算法

 Kruskal算法是基于贪心的思想得到的。首先我们把所有的边按照权值先从小到大排列,接着按照顺序选取每条边,如果这条边的两个端点不属于同一集合,那么就将它们合并,直到所有的点都属于同一个集合为止。

http://cogs.pro/cogs/problem/problem.php?pid=7

/****************************************************************************************************                                        最小生成树(Kruskal)                         ********************************************************************************************************/#include<cstdio>#include<algorithm>using namespace std;struct Edge{    int from,to,dist;    bool operator <(const Edge a)const{        return dist<a.dist;    }}a[1200000];int mFind[1550];int Find(int x){//并查集     if(mFind[x]==x)return x;    else mFind[x]=Find(mFind[x]);    return mFind[x];}int main(){    freopen("mcst.in","r",stdin);    freopen("mcst.out","w",stdout);    int n,x,a1=0;scanf("%d",&n);    for(int i=0;i<n;i++){        for(int j=0;j<n;j++){            scanf("%d",&x);            if(x!=-1&&i<j)a[a1].from=i,a[a1].to=j,a[a1++].dist=x;        }    }    for(int i=0;i<n;i++)mFind[i]=i;    sort(a,a+a1);int j=0; //将所有边排序     int fa,fb,u,v,ans=0;    for(int i=1;i<n;i++){//将连接两部分的最短边加入生成树         while(1){            u=a[j].from,v=a[j].to;            fa=Find(u),fb=Find(v);            if(fa!=fb){                ans+=a[j++].dist,mFind[fa]=fb;                break;            }            j++;        }    }    printf("%d",ans);    return 0;}

 

最小生成树