【算法】Kruskal算法(解决最小生成树问题) 含代码实现

Kruskal算法和Prim算法一样,都是求最小生成树问题的流行算法。

算法思想:

  Kruskal算法按照边的权值的顺序从小到大查看一遍,如果不产生圈或者重边,就把当前这条边加入到生成树中。

 

算法的正确性:

  由于每次加入的都是权值最小的可以加的边,所以生成的一定是最小生成树。

  (可能描述的不太准确,但是就是这个意思)

时间复杂度O(E*log(V))  (E是边数,V是顶点数)。

模板代码:

#include <iostream>
#include <algorithm>
#include <stdio.h>
using namespace std;
typedef long long ll;
//点的数量 
#define MAX_N 1000
//边的数量 
#define MAX_E 1000

struct edge{
    int u,v,cost;
}; 

bool cmp(const edge &e1,const edge& e2){
    return e1.cost < e2.cost;
}

edge es[MAX_E];   //边集 
int V,E;            //顶点和边的数量 

int par[MAX_N]; //par[i]表示i节点的父节点 
int rank[MAX_N]; // 树的高度 

//初始化n个元素
void init(int n){
    for(int i = 0;i < n; i++){
        par[i] = i;
        rank[i] = 0;
    }
} 

//查询包含x节点的树的根 
int find(int x){
    if(par[x] == x) return x;
    else return par[x] = find(par[x]); 
}

//合并 x和y所属的集合 
void unite(int x,int y){
    x = find(x);
    y = find(y);
    if(x == y) return;
    
    if(rank[x] < rank[y]){
        par[x] = y; 
    }else{
        par[y] = x;
        if(rank[x] == rank[y]) rank[x]++;
    }
}

//判断x和y是否属于同一个集合 
bool same(int x,int y){
    return find(x) == find(y);
}


//不断加入能加入的权值最小的边 
int kruskal(){
    sort(es,es+E,cmp); //按权值从小到大排序边 
    init(V);            //初始化并查集 
    int res = 0;   //生成树总权值 
    for(int i = 0;i < E ; i++){
        edge e = es[i];
        if(!same(e.u, e.v)){
            unite(e.u,e.v);
            res += e.cost;
        }
    }
    return res;
}

int main(){

    return 0;
} 
原文地址:https://www.cnblogs.com/zhangjiuding/p/7796526.html