并查集加最小堆实现的Kruskal算法…

来源:互联网 发布:linux远程桌面工具 编辑:程序博客网 时间:2024/05/22 07:48
容易证明的是,在图的最小生成树中,它的最长边在所有生成树的最长边中也是最短的,所以求所有生成树的最长边的最小值的问题和最小生成树是一个问题。
下边是并查集加最小排队实现的Kruskal算法。稍微修改下输入格式,在poj上连过了好几道最小生成树的题目。

大致思想:
a:不断的找到最小边,判断此边的两点是否已经连通,若连通则不作为并继续在堆上pop(直到pop出的边的两点所属集合不连通),若不连通则使其连通,并记录此路的代价。
重复a操作n-1次(n为点的个数);
完毕
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>
#define inf 0x6FFFFFFF

using namespace std;

struct edge
{
    int point1;
    int point2;
    int distance;
};
bool operator<(edge a,edge b)
{
    returna.distance>b.distance;
}
priority_queue<edge> pri;
int dis[550][550];
int parent[550];

int getparent(int k)
{
    if(parent[k]==k)
     return k;
    returnparent[k]=getparent(parent[k]);
}


int main()
{
    int n;
   while(scanf("%d",&n)!=EOF)
    {
       while(!pri.empty())
         pri.pop();
       for(int i=0;i<n;i++)
       {
       for(int j=0;j<n;j++)
       {
       scanf("%d",&dis[i][j]);
       }
        parent[i]=i;
       }
       for(int i=0;i<n;i++)
       for(int j=i+1;j<n;j++)
       {
           edgee;
          e.point1=i;
          e.point2=j;
          e.distance=dis[i][j];
          pri.push(e);
       }
       int sum=0;
       for(int i=1;i<n;i++)
       {
          while(!pri.empty()&&getparent(pri.top().point1)==getparent(pri.top().point2))
            pri.pop();
            if(!pri.empty())
            {
           parent[parent[pri.top().point1]]=parent[pri.top().point2];
           sum+=dis[pri.top().point1][pri.top().point2];
            }
       }
      cout<<sum<<endl;
    }
    return 0;
}
0 0
原创粉丝点击