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

来源:互联网 发布:mac下载office办公软件 编辑:程序博客网 时间:2024/05/17 22:24

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 1000struct 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;} 
原创粉丝点击