Kruskal算法

/**/ /**
 * KRUSKAL 最小生成树算法 (Minimum Spanning Tree) 
 * 输入:图g;                 // 有向图或者无向图 
 * 输出:(1)最小生成树长sum; 
 *         (2)最小生成树mst。
 * 结构: 图g用顶点数n和边集edges(优先队列)表示,两点是否连通用并查集实现。 
 * 算法:Kruskal算法  
 * 复杂度:O(|E|*log|E|)~O(|E|*log|V|) 
 
*/
 
#include 
< iostream >
#include 
< string >
#include 
< vector >
#include 
< deque >
#include 
< list >
#include 
< stack >
#include 
< queue >
#include 
< set >
#include 
< map >
#include 
< bitset >
#include 
< iterator >
#include 
< algorithm >
#include 
< numeric >
#include 
< functional >
#include 
< climits >
using   namespace  std;

struct  Edge
{
    
int u, v, w;        // u、v:两个顶点  w:权 
    Edge() { }
    Edge(
int u0, int v0, int w0):u(u0), v(v0), w(w0) { }
}
;

int  n;                     //  n : 顶点个数 
vector < Edge >  edges;         //  edges : 图g的所有边 
int  sum;                 //  sum : 最小生成树长 
vector < Edge >  mst;         //  mst : 最小生成树(用边集表示) 

class  DisjSets
{
    vector
<int> s;
    
public:
        DisjSets(
int n) : s(n, -1{ };
        
int find (int x)
        
{
            
if (s[x] < 0return x;
            
else return s[x] = find(s[x]);   // 压缩路径。 
        }
;
        
void unionSets(int root1, int root2)
        
{
            
if (s[root1] > s[root2])    // 按个数求并(个数用负数表示)。 
            {
                s[root2] 
+= s[root1];
                s[root1] 
= root2;
            }

            
else
            
{
                s[root1] 
+= s[root2];
                s[root2] 
= root1;
            }

        }
;
}


bool  Cmp( const  Edge  & lhs,  const  Edge  & rhs)
{
    
return lhs.w > rhs.w;
}
 

bool  Kruskal()
{
    DisjSets ds(n);
    make_heap(edges.begin(), edges.end(), Cmp);    
// 对边集建堆。 
    int root1, root2;
    Edge e;
    
while (!edges.empty())    // 遍历所有边, 
    {
        e 
= edges.front(); pop_heap(edges.begin(), edges.end(), Cmp); edges.pop_back();// 从未选边集中寻找最小权的边e。 
        root1 = ds.find(e.u), root2 = ds.find(e.v);    // 获取u、v所在的点集, 
        if (root1 != root2)                // 如果u、v不是同一个点集, 
        {
            sum 
+= e.w;                 // 调整最小生成树长 
            mst.push_back(e);             // 把边e放入最小生成树mst中, 
            ds.unionSets(root1, root2);    // 合并两点所在的点集。 
        }

        
if (mst.size() == n - 1return true// 如果选取边个数为n - 1,成功。
    }

    
return false;  
}


int  main()
{
    n 
= 7;
    edges.clear();
    edges.push_back(Edge(
012)); edges.push_back(Edge(024));  edges.push_back(Edge(031));
    edges.push_back(Edge(
133)); edges.push_back(Edge(1410));
     edges.push_back(Edge(
232)); edges.push_back(Edge(255));
     edges.push_back(Edge(
347)); edges.push_back(Edge(358)); edges.push_back(Edge(364));
     edges.push_back(Edge(
466));
     edges.push_back(Edge(
561));
     
     sum 
= 0;
     mst.clear();
     
if(Kruskal())
     
{
        cout 
<< sum << endl;
        
for (vector<Edge>::iterator it = mst.begin(); it != mst.end(); ++it)
            cout 
<< it-><< "->" << it-><< endl;
    }

    
else
    
{
        cout 
<< "Some vertex cann't be reached." << endl; 
    }

     
    system(
"pause");
    
return 0;
}

你可能感兴趣的:(Kruskal算法)