• POJ-图论-最小生成树模板


    POJ-图论-最小生成树模板

    Kruskal算法

    1.初始时所有结点属于孤立的集合。

    2.按照边权递增顺序遍历所有的边,若遍历到的边两个顶点仍分属不同的集合(该边即为连通这两个集合的边中权值最小的那条)则确定该边为最小生成树上的一条边,并将这两个顶点分属的集合合并。

    3.遍历完所有边后,原图上所有结点属于同一个集合则被选取的边和原图中所有结点构成最小生成树;否则原图不连通,最小生成树不存在。

    数据结构:引入边结构,并重载小于号运算符

    struct Edge
    {
        int a, b;//边的两端结点编号
        int cost;//边的权值
        bool operator <(const Edge &A)const
        {
            return cost < A.cost;//边权从小到大排列
        }
    }edge[6000];

    用并查集来实现集合操作

    void init()
    {
        for (int i = 1; i <= n; i++)p[i] = i;
        ans = 0;
    }
    
    int find(int x)
    {
        return (x == p[x]) ? x : p[x] = find(p[x]);
    }
    
    void Union(int i)//以边为单位合并
    {
        int a = find(edge[i].a);
        int b = find(edge[i].b);//查找边的两个顶点所在集合的信息
        if (a != b) //若他们属于不同集合,则选用该边
        {
            p[b] = a;//合并集合
            ans += edge[i].cost;//累加权值
        }
    }

    例 5.3 还是畅通工程

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 101;
    
    int p[N];//父结点数组
    int n;//结点数量
    int ans;//最小权值和
    
    struct Edge
    {
        int a, b;//边的两端结点编号
        int cost;//边的权值
    }edge[6000];
    
    bool cmp(Edge a, Edge b)
    {
        return a.cost<b.cost;
    }
    
    void init()
    {
        for (int i = 1; i <= n; i++)p[i] = i;
        ans = 0;
    }
    
    int find(int x)
    {
        return (x == p[x]) ? x : p[x] = find(p[x]);
    }
    
    void Union(int i)//以边为单位合并
    {
        int a = find(edge[i].a);
        int b = find(edge[i].b);//查找边的两个顶点所在集合的信息
        if (a != b) //若他们属于不同集合,则选用该边
        {
            p[b] = a;//合并集合
            ans += edge[i].cost;//累加权值
        }
    }
    
    int main()
    {
        while (scanf("%d", &n) != EOF && n != 0)
        {
            for (int i = 1; i <= n * (n - 1) / 2; i++) scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].cost);
            sort(edge + 1, edge + 1 + n * (n - 1) / 2, cmp);//起始元素为edge[1],一共n * (n - 1) / 2个待排序元素
            init();
            for (int i = 1; i <= n * (n - 1) / 2; i++) Union(i);
            printf("%d
    ", ans);
        }
        return 0;
    }
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 101;
    
    int p[N];//父结点数组
    int n;//结点数量
    int ans;//最小权值和
    
    struct Edge
    {
        int a, b;//边的两端结点编号
        int cost;//边的权值
        bool operator <(const Edge &A)const
        {
            return cost < A.cost;//边权从小到大排列
        }
    }edge[6000];
    
    void init()
    {
        for (int i = 1; i <= n; i++)p[i] = i;
        ans = 0;
    }
    
    int find(int x)
    {
        return (x == p[x]) ? x : p[x] = find(p[x]);
    }
    
    void Union(int i)//以边为单位合并
    {
        int a = find(edge[i].a);
        int b = find(edge[i].b);//查找边的两个顶点所在集合的信息
        if (a != b) //若他们属于不同集合,则选用该边
        {
            p[b] = a;//合并集合
            ans += edge[i].cost;//累加权值
        }
    }
    
    int main()
    {
        while (scanf("%d", &n) != EOF && n != 0)
        {
            for (int i = 1; i <= n * (n - 1) / 2; i++) scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].cost);
            sort(edge + 1, edge + 1 + n * (n - 1) / 2);//起始元素为edge[1],一共n * (n - 1) / 2个待排序元素
            init();
            for (int i = 1; i <= n * (n - 1) / 2; i++) Union(i);
            printf("%d
    ", ans);
        }
        return 0;
    }
    重载Edge小于号
  • 相关阅读:
    python+Appium自动化:记录遇到的坑
    python+Appium自动化:Appium元素检测
    python+Appium自动化:id元素定位
    python+Appium自动化:运行第一个appium脚本
    python+Appium自动化:Capability配置简介
    python+Appium自动化:Appium-desktop界面简介
    Appium简介以及环境安装
    monkeyrunner录制和回放功能
    monkeyrunner脚本录制和回放下载
    MonkeyRunner的简介与综合实践
  • 原文地址:https://www.cnblogs.com/yun-an/p/11111934.html
Copyright © 2020-2023  润新知