模板题,学习一下最小生成树的Kruskal算法

对于一个连通网(连通带权图,假定每条边上的权均为大于零的实数)来说,每棵树的权(即树中所有边的权值总和)也可能不同

具有权最小的生成树称为最小生成树

生成树:

  • 无向连通图的边的集合
  • 无回路
  • 连接所有的点

最小:

  • 所有边的权值之和最小

n个顶点的树有n-1条边

时间复杂度:O(ElogE)

对于稀疏图来说

按所给的边的权值从小到大排序,如果该边不与已经选的边形成环就选择它

这里用并查集来实现

第i条边的端点放在u、v数组中,权值保存在w中

这里用的是间接排序,也就是排的是每条边的序号,放在rank数组中

下面是两道模板题:

HDU 1863 畅通工程

 1 //#define LOCAL
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6
 7 const int maxn = 5000;
 8 int u[maxn], v[maxn], w[maxn], parent[maxn], rank[maxn];
 9 int m, n;
10
11 bool cmp(const int i, const int j)
12 {
13     return (w[i] < w[j]);
14 }
15
16 int GetParent(int a)
17 {
18     return parent[a] == a ? a : parent[a] = GetParent(parent[a]);
19 }
20
21 int kruskal(void)
22 {
23     int cnt = 0, weight = 0;
24     for(int i = 0; i < m; ++i)
25     {
26         int edge = rank[i];
27         int x = GetParent(u[edge]);
28         int y = GetParent(v[edge]);
29         if(x != y)
30         {
31             weight += w[edge];
32             ++cnt;
33             parent[x] = y;
34         }
35     }
36     if(cnt < n - 1)    weight = 0;
37     return weight;
38 }
39
40 int main(void)
41 {
42     #ifdef LOCAL
43         freopen("1863in.txt", "r", stdin);
44     #endif
45
46
47     while(scanf("%d%d", &m, &n) == 2 && m)
48     {
49         for(int i = 0; i < m; ++i)
50             scanf("%d%d%d", &u[i], &v[i], &w[i]);
51         for(int i = 0; i < n; ++i)    parent[i] = i;
52         for(int i = 0; i < m; ++i)    rank[i] = i;
53         sort(rank, rank + m, cmp);
54         int ans = kruskal();
55         if(ans)
56             printf("%d\n", ans);
57         else
58             printf("?\n");
59     }
60     return 0;
61 }

代码君一

POJ 1861 Network

感觉这道题略坑啊,它并没有说是多组输入啊,而且输出的第一个数是边里面的最大权值啊,数组开了1000多开小了啊,还有各种小错误啊。Orz

好吧,这些都是我的错误,上来就套模板,没有好好读题

 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 using namespace std;
 7
 8 const int maxn = 1000 + 10;
 9 int v[maxn], u[maxn], r[maxn], p[maxn], w[maxn], path[maxn];
10 int n, m, cnt, ans;
11
12 int Find(int a)
13 {
14     return p[a] == a ? a : p[a] = Find(p[a]);
15 }
16
17 bool cmp(const int i, const int j)
18 {
19     return (w[i] < w[j]);
20 }
21
22 void Kruskal(void)
23 {
24     cnt = 0, ans = -1;
25     for(int i = 0; i < m; ++i)
26     {
27         int edge = r[i];
28         int x = Find(u[edge]);
29         int y = Find(v[edge]);
30         if(x != y)
31         {
32             ans = max(ans, w[edge]);
33             p[x] = y;
34             path[cnt++] = i;
35         }
36     }
37 }
38
39 void OutPut(void)
40 {
41     printf("%d\n%d\n", ans, cnt);
42     for(int i = 0; i < cnt; ++i)
43         printf("%d %d\n", u[r[path[i]]], v[r[path[i]]]);
44 }
45
46 int main(void)
47 {
48     #ifdef LOCAL
49         freopen("1861in.txt", "r", stdin);
50     #endif
51
52     while(scanf("%d%d", &n, &m) == 2)
53     {
54         for(int i = 0; i < m; ++i)
55         scanf("%d%d%d", &u[i], &v[i], &w[i]);
56         for(int i = 0; i < n; ++i)    p[i] = i;
57         for(int i = 0; i < m; ++i)    r[i] = i;
58         sort(r, r + m, cmp);
59         Kruskal();
60         OutPut();
61     }
62
63     return 0;
64 }

代码君二

POJ 2560 Freckles

题意:给出n个点的坐标,求最小生成树的长度。奇怪的是G++没过,C++却过了

 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <cmath>
 7 using namespace std;
 8
 9 const int maxn = 5000 + 10;
10 struct Node
11 {
12     double x, y;
13 }pos[maxn];
14
15 int u[maxn], v[maxn], r[maxn], p[maxn];
16 double w[maxn];
17
18 bool cmp(const int i, const int j)
19 {
20     return (w[i] < w[j]);
21 }
22
23 int Find(int a)
24 {
25     return p[a] == a ? a : p[a] = Find(p[a]);
26 }
27
28 double Kruskal(int cnt)
29 {
30     double ans = 0.0;
31     for(int i = 0; i < cnt; ++i)
32     {
33         int edge = r[i];
34         int x = Find(u[edge]);
35         int y = Find(v[edge]);
36         if(x != y)
37         {
38             ans += w[edge];
39             p[x] = y;
40         }
41     }
42     return ans;
43 }
44
45 int main(void)
46 {
47     #ifdef LOCAL
48         freopen("2560in.txt", "r", stdin);
49     #endif
50
51     int n, cnt;
52     while(scanf("%d", &n) == 1)
53     {
54         for(int i = 0; i < n; ++i)    p[i] = i;
55         for(int i = 0; i < n; ++i)
56             scanf("%lf %lf", &pos[i].x, &pos[i].y);
57         cnt = 0;
58         for(int i = 1; i < n; ++i)
59             for(int j = 0; j < i; ++j)
60             {
61                 u[cnt] = i;
62                 v[cnt] = j;
63                 r[cnt] = cnt;
64                 w[cnt++] = sqrt((pos[i].x-pos[j].x)*(pos[i].x-pos[j].x) + (pos[i].y-pos[j].y)*(pos[i].y-pos[j].y));
65             }
66         sort(r, r + cnt, cmp);
67         printf("%.2lf\n", Kruskal(cnt));
68     }
69
70     return 0;
71 }

代码君三

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/3958599.html

最小生成树之Kruskal相关推荐

  1. 最小生成树之Kruskal算法

    图片描述 算法思想 采用贪婪策略,连续的按最小的权选择边,并且当边不产生圈时就把它作为取定的边 算法思路 问题出现 1.怎样选择最小权的边 用个排序算法 2.怎样判断加入的边是否会产生圈 (用到不相交 ...

  2. 最小生成树的Kruskal算法实现

    最近在复习数据结构,所以想起了之前做的一个最小生成树算法.用Kruskal算法实现的,结合堆排序可以复习回顾数据结构.现在写出来与大家分享. 最小生成树算法思想:书上说的是在一给定的无向图G = (V ...

  3. 最小生成树:Kruskal算法 和 Prim算法(第23章)

    武侠: 飞雪连天射白鹿,笑书神侠倚碧鸳. --金庸十四著作 飞狐外传 .雪山飞狐 .连城诀 .天龙八部 .射雕英雄传 .白马啸西风 .鹿鼎记 .笑傲江湖 .书剑恩仇录 .神雕侠侣 .侠客岛 .倚天屠龙 ...

  4. 数据结构------最小生成树之Kruskal算法

    盛年不重来,一日难再晨.及时当勉励,岁月不待人. <杂诗>陶渊明 目录 前言 一.Kruskal的几何思维 二.使用步骤 1.核心思想 2.全部测试代码 总结 前言 最小生成树算法有两种一 ...

  5. 最小生成树的Kruskal算法-详解

    最小生成树的Kruskal算法 一. 什么是最小生成树 1.1 最小生成树定义: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最 ...

  6. kruskal算法c语言,最小生成树之Kruskal算法

    上一篇文章中提到了最小生成树的Prim算法,这一节继续探讨一下最小生成树的Kruskal算法.什么是最小生成树算法上文已经交代过了,所以我们直接从Kruskal的步骤开始介绍. 1.Kruskal算法 ...

  7. ds图—最小生成树_Java: Kruskal算法生成最小生成树(邻接矩阵)

    Java: Kruskal算法生成最小生成树(邻接矩阵): package 输出: Kruskal=36: (E,F) (C,D) (D,E) (B,F) (E,G) (A,B) 分析: Java: ...

  8. 最小生成树(kruskal、prim、最小生成森林问题、严格次小生成树)

    整理的算法模板合集: ACM模板 目录 一.kruskal算法 二.prim算法 三.Boruvka算法 四.生成森林问题(K颗树) 五.最小生成树的唯一性 六.严格次小生成树 LCA优化的次小生成树 ...

  9. 最小生成树(kruskal+prime)

    kruskal模板: #include<iostream> #include<bits/stdc++.h> using namespace std;const int MAXN ...

最新文章

  1. 【C#】枚举_结构体_数组
  2. BCH的创新已打破比特币的共识效应
  3. linux ssh和sftp区别,使用 SSH 和 SFTP 协议
  4. 在ubuntu下安装free pascal
  5. MYSQL主从同步故障一例及解决过程
  6. Fix chrome 下flash crash的问题
  7. Laravel Query Builder 复杂查询案例:子查询实现分区查询 partition by
  8. Spring中注解注入bean和配置文件注入bean
  9. 流计算技术实战 - 超大维表问题
  10. 实现一个符合标准的Promise
  11. MongoDB 自动分片 auto sharding
  12. 使用ServletContextListener关闭Redisson连接
  13. idea解决Untracked Files Prevent Merge问题
  14. 僵尸网络 DDoS 攻击活动分析
  15. bootstrap 5 表单验证
  16. SQLyog连接不上
  17. Win10无法使用内置管理员账户打开应用解决办法
  18. 第四次面试----华数电力科技有限公司
  19. Windows7 Embedded Standard x64更新代码80072EFE解决方法
  20. java需要用到英语_javaSE常用的英语单词

热门文章

  1. linux操作系统上课,Linux操作系统使用的文件系统是
  2. mysql聚合函数count用法_MySQL中聚合函数count的使用和性能优化技巧
  3. antd 函数组件_React - 组件:函数组件
  4. 如何加速云原生数据应用?这个开源项目备受关注
  5. 云原生 DevOps 的 5 步升级路径
  6. 阿里云 OpenYurt 成为 CNCF 沙箱项目,加速原生 Kubernetes 边缘场景全覆盖
  7. 初探云原生应用管理(二): 为什么你必须尽快转向 Helm v3
  8. APP元素事件操作API
  9. Python中字典的介绍以及常用操作
  10. python元类的使用_Python 元类使用讲解