zoukankan      html  css  js  c++  java
  • 贪心算法之Kruskal

    克鲁斯卡尔Kruskal算法同Prim算法一样,都是求最小生成树。Kruskal是不断的找最短边,加入集合,且不构成回路。

    所以,我们可以给每个点定义一个集合,一边的起点和终点查看是否属于同一集合,如果是说明是回路,不成立,找下一条边。如果不属于同一集合,则成立,并把其中的一个集合的全部节点的集合改为另外一个集合,进行统一。

    具体代码如下:

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define MAXNODE 1000
    
    int n,m;
    struct Edge{
        int u;
        int v;
        int w;
    } e[MAXNODE * MAXNODE];
    
    int nodeset[MAXNODE]; //每个顶点的集合
    
    int Kruskal(int n);
    
    bool Merge(int u, int i);
    
    bool comp(Edge a, Edge b){
        return a.w < b.w;
    }
    
    void Init(int n){
        for(int i=0; i < n; i++){
            nodeset[i] = i;
        }
    }
    
    int main(){
        cout<<"请输入节点数n和边数m:";
        cin>>n>>m;
        Init(n);
        cout << "请输入节点边的权值:";
        for(int i = 0; i < m; i++){
            cin>>e[i].u>>e[i].v>>e[i].w;
        }
        sort(e, e+m, comp);
        int ans = Kruskal(n);
        cout<<ans<<endl;
    }
    
    int Kruskal(int n) {
        int ans = 0;
        for(int i = 0; i < m; i++){
            if(Merge(e[i].u, e[i].v)){//可以合并
                ans += e[i].w;
                n--;
                if(n==1)
                    return ans;
            }
        }
        return 0;
    }
    
    bool Merge(int u, int i) {
        int a = nodeset[u];
        int b = nodeset[i];
        if(a == b)
            return false;
        //归并节点集合
        for(int j = 0; j < n; j++){
            if(nodeset[j] == b){
                nodeset[j] = a;
            }
        }
        return true;
    }

    同时,与Prim算法相比,因为Kruskal是按照边进行的,所以适合边少的情况,即稀疏图。而Prim是按照点进行的,比较适合稠密图。

  • 相关阅读:
    【Oracle】安装
    【Java】String,StringBuffer与StringBuilder的区别??
    【Java】基本数据类型长度
    静态构造函数
    【算法】递归算法
    【JavaScript】JavaScript教程之------------------JavaScript实现
    【Android】listview优化
    【JAVA EE企业级开发四步走完全攻略】
    Eclipse下Tomcat插件的安装
    Android工具
  • 原文地址:https://www.cnblogs.com/gpf951101/p/9130468.html
Copyright © 2011-2022 走看看