Kruskal 最小生成树的总结

本文通过C++代码介绍了如何使用Kruskal算法求解最小生成树。通过结构体Edge定义边,利用排序和查找父节点的函数进行集合合并,避免形成环路。在主函数中读取图的边,对边按权重排序,然后逐条加入最小生成树,直到连接所有节点。最后输出最小生成树的最大边权值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写了3,4天的最小生成树,里边写了报告和没写的加起来也有十题左右了。发现这些简单的算法里头有不少的pin。特别是2421让人抓狂,bug一个接一个,wa了不下十数次后,在波波的指导下成功的ac了,后来自己又找到了原来程序的几个bug。
原先写这篇报告的时候以为Kruskal比Prim优秀许多。后来波波跟我说Prim也是很强的,于是我分别用Kruskal和Prim写了Poj1789,发现原来Prim也是很strong的,用的时间几乎只有Kruskal的20%,囧。于是现在把这篇报告改为Kruskal最小生成树总结,顺便把标程贴出来以后好找~~
 
下面的是Kruskal:
  1. //这段代码用Kruskal来解决
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <memory.h>
  5. #include <algorithm>
  6. using namespace std;
  7. // 边类型
  8. typedef struct Edge{
  9.     int x;
  10.     int y;
  11.     int weigh;
  12.     bool operator() ( Edge a,Edge b) {
  13.         return (a.weigh < b.weigh);
  14.     }
  15. }Edge;
  16. //最多可能的边
  17. Edge edge[251001];
  18. int parent[501];
  19. //用于qsort()的比较函数
  20. int compare(const void*a,const void *b)
  21. {
  22.     return ((Edge*)a)->weigh - ((Edge*)b)->weigh;
  23. }
  24. // 找父节点并压缩路径
  25. int Find(int x)
  26. {
  27.     if( parent[x] >= 0)
  28.         parent[x] = Find(parent[x]);
  29.     else
  30.         return x;
  31.     return parent[x];
  32. }
  33. // 合并集合
  34. void Union(int x,int y)
  35. {
  36.     x = Find(x);
  37.     y = Find(y);
  38.     // 注意:这里的重边判断很重要
  39.     if( x == y)
  40.         return ;
  41.     if(parent[x] < parent[y]) 
  42.         parent[y] = x;
  43.     else
  44.         if(parent[x] > parent[y])
  45.             parent[x] = y;
  46.         else {
  47.             parent[x]--;
  48.             parent[y] = x;
  49.         }
  50. }
  51. int main()
  52. {
  53.     int m,n;
  54.     int count = 0;
  55.     scanf("%d",&n);
  56.     forint i = 0; i < n; i++) {
  57.         scanf("%d",&m);
  58.         memset(parent,-1,m * sizeof(int));
  59.         forint j = 0; j < m; j++)
  60.             forint k = 0; k < m; k++) {
  61.                 scanf("%d",&edge[count].weigh);
  62.                 edge[count].x = j;
  63.                 edge[count++].y = k;
  64.             }
  65.         sort(edge,edge + m * m,Edge());
  66.         count = 1;
  67.         int max;
  68.         // 忽略那些为0的节点,有m个,然后从小到大去边
  69.         forint j = m; j < (m * m) && count < m; j++)
  70.             if(Find(edge[j].x) != Find(edge[j].y)) {
  71.                 count ++;
  72.                 Union(edge[j].x,edge[j].y);
  73.                 max = edge[j].weigh;
  74.             }
  75.         printf("%d/n",max);
  76.     }
  77. }

唉,还是有parent好啊~~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值