最小生成树模版(Kruskal)

最近研究了这东西 感觉十分有用 在对于少边的情况下效果十分明显

 

本程序使用优先队列存储边信息 使用并查集判定是否已经连通 O(eloge)的复杂度

 

 

#include <iostream>
#include 
<queue>
using namespace std;

const long MAXN=10000;

long hash[MAXN];

long m,n;//点数 边数
//m标号从1开始
typedef struct
{
    
long from;
    
long to;
    
long cost;
}
Edge;

bool operator <(const Edge &a, const Edge &b)
{
    
return a.cost>b.cost;
}


priority_queue
<Edge> q;
Edge e;

void MakeSet()
{
    
long i;
    
for (i=0;i<=m;++i)
    
{
        hash[i]
=i;
    }

}


long Find(long i)
{
    
long r=i;
    
while (hash[r]!=r)
    
{
        r
=hash[r];
    }

    
    
while (hash[i]!=r)
    
{
        
long j=hash[i];
        hash[i]
=r;
        i
=j;
    }


    
return r;
}


void Unition(long x,long y)
{
    
long fx=Find(x);
    
long fy=Find(y);
    
    
if (fx!=fy)
    
{
        hash[fx]
=fy;
    }

}


void Init()
{

    
while (!q.empty())
    
{
        q.pop();
    }

    MakeSet();
    
long i;
    
for(i=0;i<n;++i)
    
{
        scanf(
"%ld %ld %ld",&(e.from),&(e.to),&(e.cost));//得到源点 终点
        q.push(e);
        
//以下为无向图的处理
        swap(e.from,e.to);
        q.push(e);
    }

}


void print(long cost)
{
    printf(
"%ld\n",cost);
}


void Kruskal()
{
    Init();

    
long t=0;//表示合并次数

    
long cost=0;

    Edge e;
    
while (!q.empty()&&t<m-1)
    
{
        e
=q.top();
        
long v1=e.from;
        
long v2=e.to;
        
if (Find(v1)!=Find(v2))
        
{
            Unition(v1,v2);
            cost
+=e.cost;
            
++t;
        }

        q.pop();
    }


    print(cost);
}


int main()
{
    
while(scanf("%ld %ld",&m,&n)!=EOF)//输入点与边
    {
        Kruskal();
    }

    
return 0;
}


posted @ 2008-07-25 19:32  Hdu-Lost  阅读(412)  评论(2编辑  收藏  举报