zoukankan      html  css  js  c++  java
  • Kruskal 最小生成树

    Kruskal算法:

    ①用并查集实现

    ②构造一个只含 n 个顶点,边集为空的子图,把子图中各个顶点看成各棵树上的根结点

    ③sort()排序升序,依次从边集 E 中选取一条权值最小的边,如果该条边的两个顶点分属不同的树,则把两棵树合成一棵树。若该条边的两个顶点已落在同一棵树上,跳过,取下一条权值最小的边再试之。子图中含有 n-1 条边就结束,此时森林中只有一棵树

    注意:顶点个数的最大值和边的个数的最大值是不一样的,要单独定义一个MAX_EDG

    #include <stdio.h>
    #include <algorithm>
    #define MAX 100
    #define MAX_EDG 1000 
    
    using namespace std;
    
    typedef struct Node{
        int u;
        int v;
        int w;
    }Node;
    
    
    Node map[MAX_EDG];    //注意:顶点数和边数的最大值是不一样的,要分别定义 
    int father[MAX];    //自己的父亲 
    int rank_[MAX];        //
    
    bool cmp(Node a, Node b){       //比较函数
        return a.w < b.w;    //从小到大 升序 
    }
    
    int find(int x){
        if(father[x]==x)    return x;
        else return    father[x]=find(father[x]);        //向上找父亲直到找到根节点 
    }
    
    void unite(int x, int y){
        if(find(x) == find(y))    return;
        else{
            int x_root=find(x);
            int y_root=find(y);
            if(rank_[x_root] > rank_[y_root])            //按秩合并   //比较的是树根x_root和y_root的秩 ,不是x和y的 
                father[y_root]=x_root;
            else if(rank_[y_root] > rank_[x_root])
                father[x_root]=y_root;
            else{                            //两个树根的秩一样的话,任意合并到其中一个树根中,然后秩++ 
                father[x_root]=y_root;
                rank_[y_root]++;
            }    
        }
    }
    
    void init(int n){
        for(int i=1;i<=n;i++){
            father[i]=i;        //自己是自己的父亲 
            rank_[i]=0;            //初始高度为0 
        }
    }
    
    int main(){
        int n,m;
        int count,sum;
        int u,v,w;
        while(scanf("%d %d",&n,&m)!=EOF){
            init(n);
            for(int i=1;i<=m;i++)
                scanf("%d %d %d",&map[i].u,&map[i].v,&map[i].w);
            sort(map+1, map+m+1, cmp);            //sort排序,由小到大 
            count=0;
            sum=0;
            for(int i=1;i<=m;i++){
                if(count==n-1)    break;            //n个顶点被n-1条边连接就跳出 
                u=map[i].u;
                v=map[i].v;
                w=map[i].w;
                if(find(u)!=find(v)){        //如果不在同一个子树就合并 
                    unite(u,v);
                    count++;
                    sum+=w;
                }
            }
            printf("%d
    ",sum);         //sum是n-1条边的边权和 
        }
        return 0;
    }
  • 相关阅读:
    Odd sum CodeForces
    Chips CodeForces
    Secrets CodeForces
    Voting CodeForces
    Jury Meeting CodeForces
    Planning CodeForces
    Maxim Buys an Apartment CodeForces
    Chemistry in Berland CodeForces
    Monitor CodeForces
    Four Segments CodeForces
  • 原文地址:https://www.cnblogs.com/shiliuxinya/p/12194545.html
Copyright © 2011-2022 走看看