最小生成树(Krukal & Prim)

Posted z8875

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小生成树(Krukal & 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;
      }
      



以上是关于最小生成树(Krukal & Prim)的主要内容,如果未能解决你的问题,请参考以下文章

poj1861 最小生成树 prim &amp; kruskal

数据结构与算法系列----最小生成树(Prim算法&amp;Kruskal算法)

最小生成树模板kruskal & prim

图的最小生成树prim算法模板

数据结构与算法系列----最小生成树(Prim算法&Kruskal算法)

hdu 1162 Eddy&#39;s picture (Kruskal算法,prim算法,最小生成树)