码迷,mamicode.com
首页 > 其他好文 > 详细

最小生成树

时间:2017-05-16 23:09:46      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:using   turn   can   stdout   i++   strong   namespace   while   部分   

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;
}

 

最小生成树

标签:using   turn   can   stdout   i++   strong   namespace   while   部分   

原文地址:http://www.cnblogs.com/bennettz/p/6863767.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!