zoukankan      html  css  js  c++  java
  • 最小生成树(一)kruskal

    今天写一篇关于最小生成树的番外篇,以前写最小生成树总是用的prim,关于kruskal只是知道一些原理,一直也没有时间去学,今天偶然看了一些并查集,才想起了这个算法

    会想起刚刚(预)学过的数据结构,来解释一下它的原理:

    先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。-------百度百科

    通俗一点讲,给定加权无向图G(E,V),将所有边取出只留下点集,然后边按权值从小到大排序后,加入点集中对应该条边原本连接的点的关系,每加入一条边,都要检查加入这条边后是否会与之前加入的边构成环,如果成环,则该边不可取,进行下一条边的的判断,当加入n-1(图有n个顶点)条边后,最小生成树毕.

    证明(摘自百度百科):

    1. 这样的步骤保证了选取的每条边都是桥,因此图G构成一个树。
    2. 为什么这一定是最小生成树呢?关键还是步骤3中对边的选取。算法中总共选取了n-1条边,每条边在选取的当时,都是连接两个不同的连通分量的权值最小的边
    3. 要证明这条边一定属于最小生成树,可以用反证法:如果这条边不在最小生成树中,它连接的两个连通分量最终还是要连起来的,通过其他的连法,那么另一种连法与这条边一定构成了环,而环中一定有一条权值大于这条边的边,用这条边将其替换掉,图仍旧保持连通,但总权值减小了。也就是说,如果不选取这条边,最后构成的生成树的总权值一定不会是最小的。

    时间复杂度:(eloge)e为边数,这里一定要分清.

    #include <bits/stdc++.h>
    using namespace std;
    struct node{
    int x;
    int y;
    int w;
    }e[200005];
    int f[5055];
    int n,m,total;
    bool camp(node a,node b)//sort()重载函数
    {
        return a.w<b.w;
    }
    int find(int x)//并查
    {
        if(f[x]==x)
        {
            return x;
        }
        else
        {
            f[x]=find(f[x]);
            return f[x];
        }
    }
    int kruskal()
    {
        for(int i=1;i<=m;i++)
        {
            int u=find(e[i].x);
            int v=find(e[i].y);
            if(u!=v)//如果不在一个集合中
            {
                total+=e[i].w;
                f[u]=v;
                n--;
                if(n==1)//加够了n-1条边
                    break;
            }
        }
        return total;
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            f[i]=i;
        for(int i=1;i<=m;i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            e[i].x=x;
            e[i].y=y;
            e[i].w=z;
        }
        sort(e+1,e+m+1,camp);
        kruskal();
        if(n==1)
        cout<<total<<endl;
        else//不能构成最小生成树
            cout<<"orz"<<endl;
        return 0;
    }
  • 相关阅读:
    7.1 异常处理结构
    第 7 章 异常处理结构、代码测试与调试
    6.4.2 案例精选
    6.4.1 标准库 os、os.path 与 shutil 简介
    设计模式----装饰模式
    设计模式---单例模式
    设计模式--工厂方法模式
    设计模式-简单工厂模式
    设计模式基础知识
    更改Mysql数据库中的数据出现乱码问题
  • 原文地址:https://www.cnblogs.com/iloveysm/p/12288670.html
Copyright © 2011-2022 走看看