zoukankan      html  css  js  c++  java
  • 最小生成树(Kruskal & Prim)

    例题

    kruskal

    • Kruskal算法通过并差集维护,从到小枚举每条边,如果两端点不在一个集合,将两端点所在集合合并,并将边权累加到答案中

    • 时间复杂度为(O(m log m))

    • 评测记录

      • code
        #include <cstdio>
        #include <algorithm>
        using namespace std;
        const int N = 5005, M = 2e5+5;
        struct side {
            int x, y, d;
        }e[M];
        bool operator < (side a, side b) {
            return a.d < b.d;
        }
        int n, m, f[N], ans, cnt;
        int found(int x) {
            return x == f[x] ? x : (f[x] = found(f[x]));
        }
        void kruskal() {
            for (int i = 1; i <= m; i++) {
                int x = found(e[i].x), y = found(e[i].y);
                if (x == y) continue;
                f[x] = y;
                ans += e[i].d;
                if (++cnt == n-1) return;//最小生成树上最多n-1条边
            }
        }
        int main() {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= m; i++)
                scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].d);
            sort(e + 1, e + m + 1);//排序
            for (int i = 1; i <= n; i++) f[i] = i;//并查集初始化
            kruskal();
            if (cnt == n-1) printf("%d
        ", ans);
            else puts("orn");//奇奇怪怪的输出,其实他没有这个测试点
            return 0;
        }
        

    prim

    • Prim算法思想类似于Dijkatra。
      维护一个数组 d[x] 节点 x 与已确定是最小生成树集合中的节点之间权值最小的边的权值
      每次从未标记的节点中选出 d 值最小的点,将其标记,在更新其他点的 d 值

    • 时间复杂度为(O(n^2)),使用堆优化可以到(O(mlogn))(这里写的是堆优化后的板子) 但是这样不如Kruskal方便,
      因此,Prim主要用于稠密图,尤其是完全图的求解

    • 评测记录

      • code
        #include <queue>
        #include <cstdio>
        #include <cstring>
        using namespace std;
        const int N = 5005, M = 2e5+5;
        struct side{
            int t, d, next;
        }e[M<<1];
        int head[N], tot;
        void add(int x, int y, int z) {
            e[++tot].next = head[x];
            head[x] = tot;
            e[tot].t = y;
            e[tot].d = z;
        }
        priority_queue< pair<int, int> > q;
        int n, m, d[N], ans, cnt;
        bool v[N];
        void prim() {
            memset(d, 0x3f, sizeof(d));
            q.push(make_pair(d[1] = 0, 1));
            while (!q.empty() && cnt < n) {
                int x, w;
                x = q.top().second;
                w = -q.top().first;
                q.pop();
                if (v[x]) continue;
                v[x] = 1;
                ans += w;
                cnt++;
                for (int i = head[x]; i; i = e[i].next) {
                    int y = e[i].t;
                    if (d[y] > e[i].d) {
                        d[y] = e[i].d;
                        q.push(make_pair(-d[y], y));
                    }
                }
            }
        }
        int main() {
            scanf("%d%d", &n, &m);
            while (m--) {
                int x, y, z;
                scanf("%d%d%d", &x, &y, &z);
                add(x, y, z); add(y, x, z);
            }
            prim();
            if (cnt == n) printf("%d
        ", ans);
            else puts("orn");
            return 0;
        }
        
  • 相关阅读:
    【前端】Node.js学习笔记
    【前端】Web前端学习笔记【2】
    【Python】我的Python学习笔记【2】【using Python 3】
    【iOS】Foundation框架 学习笔记
    了解数据库对象
    对Bootstrap的粗略认识
    win10电脑突然开不了热点,怎么办
    excel 怎么将表中的空格都转变为0???
    cpno在数据库里面是什么意思??
    ·ps 的暂存盘空间不够
  • 原文地址:https://www.cnblogs.com/Z8875/p/13229244.html
Copyright © 2011-2022 走看看