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

    克鲁斯卡尔算法

    适合于求边稀疏的网的最小生成树

    思路:

    将每条边的权值按从小到大的顺序排列,然后遍历,将边放回图中,如果此时的连线不能形成环,则继续,否则将此边丢弃,直到放进去n-1条边(n个点连通需要n-1条边)结束

     

    用结构体存储顶点和边,sort排序

    struct bian//存储边的信息
    {
        int x,y,w;
    }a[maxn];

    如何判断是否成环----并查集(https:////www.cnblogs.com/subject/p/12386581.html

    如果最终父类相同说明在一个集合中(形成环)

    int getfather(int x)//递归找父类
    {
        if(father[x]==x) return x;
        father[x] = getfather(father[x]);
        return father[x];
    }
    void unionm(int x,int y)//合并
    {
        int fa,fb;
        fa = getfather(x);
        fb = getfather(y);
        if(fa!=fb) father[fa] = fb;
    }
    void Init()//父类初始化
    {
        for(int i = 1;i <= n;i++)
            father[i] = i;
        return;
    };
    
    void Kruskal()
    {
        int ans = 0;//记录权值
        int k = 0;//记录已经连几条边
        for(int i=1;i<=m;i++)
        {
            if(getfather(a[i].x)!=getfather(a[i].y))//父类不同,说明是两个集合,此边可取
            {
                unionm(a[i].x,a[i].y);//合并为一个集合
                ans+=a[i].w;//权值相加
                k++;
            }
            if(k==n-1) break;
        }
        if(k==n-1) cout<<ans<<endl;
        else cout<<"impossible"<<endl;//遍历完 也不够n-1条 说明不能形成通路。
    }

    完整代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 2e5+5;
    
    struct bian//存储边的信息
    {
        int x,y,w;
    }a[maxn];
    
    int father[maxn];//每个点的最终父类
    int n,m;
    bool cmp(const bian& a,const bian& b)
    {
        return a.w<b.w;
    }
    
    int getfather(int x)//递归找父类
    {
        if(father[x]==x) return x;
        father[x] = getfather(father[x]);
        return father[x];
    }
    void unionm(int x,int y)//合并
    {
        int fa,fb;
        fa = getfather(x);
        fb = getfather(y);
        if(fa!=fb) father[fa] = fb;
    }
    void Init()//父类初始化
    {
        for(int i = 1;i <= n;i++)
            father[i] = i;
        return;
    };
    
    void Kruskal()
    {
        int ans = 0;
        int k = 0;
        for(int i=1;i<=m;i++)
        {
            if(getfather(a[i].x)!=getfather(a[i].y))
            {
                unionm(a[i].x,a[i].y);
                ans+=a[i].w;
                k++;
            }
            if(k==n-1) break;
        }
        if(k==n-1) cout<<ans<<endl;
        else cout<<"impossible"<<endl;
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>a[i].x>>a[i].y>>a[i].w;
        }
        Init();
        sort(a+1,a+1+m,cmp);
    
        Kruskal();
    
        return 0;
    }
    View Code
  • 相关阅读:
    python学习
    当时的月亮 王菲
    谈谈写程序与学英语(转载)
    excel 列索引(数字)转列名
    爆款PHP面试题
    关于PDO取得结果集的数据类型为string的问题
    分享几款常用的API/文档浏览器
    php写错命名空间 导致catch不到异常
    iOS图片上传后被旋转的问题
    vi写完文件保存时才发现是readonly😂
  • 原文地址:https://www.cnblogs.com/subject/p/12392053.html
Copyright © 2011-2022 走看看