克鲁斯卡尔(kruskal)法求最小生成树

来源:互联网 发布:淘宝打包能学到什么 编辑:程序博客网 时间:2024/05/19 12:11

kruskal

基本思想:

 克鲁斯卡尔算法的基本思想是以边为主导地位,始终选择当前可用(所选的边不能构成回路)的最小权植边。所以Kruskal算法的第一步是给所有的边按照从小到大的顺序排序。这一步可以直接使用库函数qsort或者sort。接下来从小到大依次考察每一条边(u,v)。

具体实现过程如下:

 <1> 设一个有n个顶点的连通图为G(V,E),最初先构造一个只有n个顶点,没有边的非连通图T={V,空}。 <2> 在G中选择一条具有最小权植的边时,若该边的两个顶点在T中连接不会形成环(环可以用并查集判断(是否为同一个祖先)),则将此边加入到T中;否则,将此边舍去(此后永不选用这条边),重新选择一条权植最小的边。(可以先排序) <3> 如此重复下去,直到所有顶点在连通为止。
#include<bits/stdc++.h>using namespace std;int v[10000010];struct node{    long long int u,v,w;} a[10000010];long long int cmp(node a,node b){    return a.w<b.w;}long long int dd(int x) // 使用并查集{    return v[x]==x?v[x]:v[x]=dd(v[x]);}long long int f(int a,int b){    long long int x=dd(a),y=dd(b);    if(x!=y)    {        v[y]=x;        return 1;    }    else return 0;}int main(){    long long int i,n,m,s=0,temp=0;    scanf("%lld%lld",&n,&m);    for(i=0; i<=n+2; i++)   v[i]=i;    for(i=1; i<=m; i++)    {        scanf("%lld%lld%lld",&a[i].u,&a[i].v,&a[i].w);    }    sort(a+1,a+1+m,cmp);// 边从小到大排    for(i=1; i<=m; i++)    {        if(temp==n-1) break;//temp表示加入的边的条数,如有n-1条且无环,,则此图定为一棵树        if(f(a[i].u,a[i].v))//祖先不为同一个,,不会形成环        {            temp++;            s+=a[i].w;        }    }    printf("%lld",s);    return 0;}
阅读全文
0 0
原创粉丝点击