算法简讲部分:

Kruskal算法:

基于贪心策略大致过程分为第三步:1. 我们先用结构体把每条边的端点和权值记录下来,然后对每条边按权值进行排序2. 因为 使图连通最少需要n-1 条边,所以我们依次从小到大遍历所有的边,如果 该边的端点不在当前的连通分支中,则将其加入其中3. 当遍历到最后一条边或添加 边数 超过n-1时,结束遍历但还有一点要注意的,并不是每次算法得出的图都是连通的,如果边的数量没达到n-1就结束了遍历,即所有边都已经遍历完了,那我们所求的最小生成树是不存在的。

参考代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct nn
{int x;int y;int t;
}s[500010];
int bcj[10010];
int find(int x)
{if(bcj[x]<0)return x;return bcj[x] = find(bcj[x]);
}
void join(int x,int y)
{x = find(x);y = find(y);if(x==y)return ;bcj[x]+=bcj[y];bcj[y] = x;
}
bool cmp(nn x,nn y)
{return x.t<y.t;
}
int main()
{int cnt = 0;int ans = -1;int n,m;scanf("%d %d",&n,&m);for(int i = 1;i<=m;i++){scanf("%d %d %d",&s[i].x,&s[i].y,&s[i].t);}for(int i = 1;i<=n;i++)bcj[i] = -1;sort(s+1,s+1+m,cmp);for(int i = 1;i<=m;i++){int x = find(s[i].x);int y = find(s[i].y);if(x==y)continue;ans += s[i].t;//具体操作看题意join(x,y);cnt++;if(cnt==n-1)break;}if(cnt==n-1)printf("%d\n",ans);elseprintf("orz\n");
} 

Prim算法:

基于贪心策略Prim算法构建最小生成树的过程是:先构建一棵只包含根结点V1的树A,然后每次在连接树A结点和图 G中树A以外的结点的所有边中,选取一条权重最小的边加入树A,直至树A覆盖图G中的所有结点。

参考代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N = 1e5+9;
int bcj[N];
struct nn
{int x,y,z;
}s[N];
int find(int x)
{if(bcj[x]<0)return x;elsereturn bcj[x] = find(bcj[x]);
}
void join(int x,int y)
{x = find(x);y = find(y);if (x == y)return;bcj[x] += bcj[y];bcj[y] = x;
}
bool cmp(nn x,nn y)
{return x.z<y.z;
}
int main()
{int n,m;scanf("%d %d",&n,&m);memset(bcj,-1,sizeof bcj);for(int i = 1;i<=m;i++){int x,y,z;scanf("%d %d %d",&x,&y,&z);s[i].x = x,s[i].y = y,s[i].z = z;}sort(s+1,s+1+m,cmp);int cnt =  0,ans = 0;for(int i = 1;i<=m;i++){int x = find(s[i].x);int y = find(s[i].y);if(x==y)continue;cnt++;ans += s[i].z;//具体操作看题意join(x,y);if(cnt==n-1)break;}if(cnt==n-1)printf("%d\n",ans);elseprintf("-1\n");} 

两种算法的不同和相同之处相同之处:

两种算法都是基于贪心思想,以及避环的操作不同之处:在避环的实现上Kruskal算法采用的是并查集,Prim算法则是维护了两个块(已经在生成树内的和未在生成树内的)

Kruskal算法例题:

畅通工程续

HDU - 1874

题目如下:

某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。

Input

本题目包含多组数据,请处理到文件结束。
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。

Output

对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.

Sample Input

3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2

Sample Output

2
-1

AC代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct nn
{int x, y;double jl;
}s[1009];
int bcj[1009];
struct mm
{int x, y;
}arr[1009];
int find(int x)
{if (bcj[x] < 0)return x;return bcj[x] = find(bcj[x]);
}
void join(int x, int y)
{x = find(x);y = find(y);if (x == y)return;bcj[x] += bcj[y];bcj[y] = x;
}
double js(int x1, int y1, int x2, int y2)
{double d = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));return d;
}
bool cmp(nn x, nn y)
{return x.jl < y.jl;
}
int main()
{int t;scanf("%d", &t);while (t--){double ans = 0;int cnt = 0;int c;scanf("%d", &c);for (int i = 1; i <= c; i++){scanf("%d %d", &arr[i].x, &arr[i].y);}memset(bcj, -1, sizeof bcj);int num = 1;for (int i = 1; i <= c; i++){int x1 = arr[i].x;int y1 = arr[i].y;for (int j = i + 1; j <= c; j++){int x2 = arr[j].x;int y2 = arr[j].y;double d = js(x1, y1, x2, y2);//不能小于10米,也不能大于1000if (d >= 10 && d <= 1000){s[num].x = i;s[num].y = j;s[num].jl = d;num++;}}}sort(s + 1, s + num, cmp);for (int i = 1; i < num; i++){int x = s[i].x;int y = s[i].y;if (find(x) == find(y))continue;cnt++;ans += s[i].jl;join(x, y);if (cnt == c - 1)break;}if (cnt == c - 1)printf("%.1lf\n", ans * 100);elseprintf("oh!\n");}
}

Prim算法例题:

北极通讯网络

题目如下:

原题来自:Waterloo University 2002

北极的某区域共有 nnn 座村庄,每座村庄的坐标用一对整数 (x,y) 表示。为了加强联系,决定在村庄之间建立通讯网络。通讯工具可以是无线电收发机,也可以是卫星设备。所有的村庄都可以拥有一部无线电收发机, 且所有的无线电收发机型号相同。但卫星设备数量有限,只能给一部分村庄配备卫星设备。

不同型号的无线电收发机有一个不同的参数 d,两座村庄之间的距离如果不超过 d 就可以用该型号的无线电收发机直接通讯,d 值越大的型号价格越贵。拥有卫星设备的两座村庄无论相距多远都可以直接通讯。

现在有 k 台卫星设备,请你编一个程序,计算出应该如何分配这 k 台卫星设备,才能使所拥有的无线电收发机的 d 值最小,并保证每两座村庄之间都可以直接或间接地通讯。

例如,对于下面三座村庄:

其中 |AB|= 10, |BC|= 20, |AC|= 10*sqrt{5}≈22.36

如果没有任何卫星设备或只有 1 台卫星设备 (k=0或 k=1),则满足条件的最小的 d=20,因为 A和 B,B 和 C 可以用无线电直接通讯;而 AAA 和 CCC 可以用 BBB 中转实现间接通讯 (即消息从 A 传到 B,再从 B 传到 C);

如果有 2 台卫星设备 (k=2),则可以把这两台设备分别分配给 B 和 C ,这样最小的 d 可取 10,因为 A 和 B 之间可以用无线电直接通讯;B 和 C 之间可以用卫星直接通讯;A 和 C 可以用 B 中转实现间接通讯。

如果有 3 台卫星设备,则 A,B,C 两两之间都可以直接用卫星通讯,最小的 d 可取 0。

输入格式

第一行为由空格隔开的两个整数 n,k;

第 2∼n+1 行,每行两个整数,第 i 行的 xi,yi​ 表示第 i 座村庄的坐标 (xi,yi)。

输出格式

一个实数,表示最小的 d 值,结果保留 2 位小数。

样例

Input Output
3 2
10 10
10 0
30 0
10.00

数据范围与提示

对于全部数据,1≤n≤500,0≤x,y≤10e4,0≤k≤100。

AC代码如下:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 1e6 + 9;
int bcj[N];
struct nn
{int x, y;double z;
}s[N];
struct mm
{int x, y;
}arr[1009];
int find(int x)
{if (bcj[x] < 0)return x;elsereturn bcj[x] = find(bcj[x]);
}
void join(int x, int y)
{x = find(x);y = find(y);if (x == y)return;bcj[x] += bcj[y];bcj[y] = x;
}
bool cmp(nn x, nn y)
{return x.z - y.z < 0.000000001;
}
double distance(int x1, int y1, int x2, int y2)
{double d = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));return d;
}
int main()
{int n, k;scanf("%d %d", &n, &k);for (int i = 1; i <= n; i++){scanf("%d %d", &arr[i].x, &arr[i].y);}int num = 0;for (int i = 1; i <= n; i++){int x1 = arr[i].x;int y1 = arr[i].y;for (int j = i + 1; j <= n; j++){int x2 = arr[j].x;int y2 = arr[j].y;double d = distance(x1, y1, x2, y2);s[++num].x = i, s[num].y = j, s[num].z = d;}}memset(bcj, -1, sizeof bcj);sort(s + 1, s + 1 + num, cmp);double ans = 0;int cnt = 0;for (int i = 1; i <= num; i++){int x = s[i].x;int y = s[i].y;if (find(x) == find(y))continue;cnt++;ans = s[i].z;join(x, y);if (cnt == n - k)break;}printf("%.2lf\n", ans);
}

找的两个例题都是板子题,并且非常相似(狗头保命,哈哈)

最后,感谢您的阅读!!!

一切伟大的行动和思想,都有一个微不足道的开始。――加缪

最小生成树(Kruskal算法+Prim算法)简单讲解+最小生成树例题 acm寒假集训日记22/1/8相关推荐

  1. spfa(STL写法)简单讲解+最短路(spfa)例题 acm寒假集训日记22/1/7

    前言:SPFA(Shortest Path Faster Algorithm)算法是求单源最短路线的一种算法,它是Bellman-ford的队列优化,它是一种十分高效的最短路算法. spfa 其实可以 ...

  2. KMP算法(字符串匹配问题)acm寒假集训日记22/1/19

    首先,先看一道例题: 如果不考虑超时的话,我们完全可以用最朴素的方法(暴力)去求 //暴力算法(n*m) int ViolentMatch(char *s,char *p) {int sLen = s ...

  3. 扩展欧几里得exgcd算法 acm寒假集训日记22/1/12

    数学证明 ax + by = gcd(a,b) 令gcd(a,b) = d 得:ax + by = d ① 因为:gcd(a,b) = gcd(b,a%b) 所以:bx + a%b * y = d b ...

  4. 最小生成树 Kruskal 和 Prim算法及堆优化

    目录 生成树/最小生成树是什么. 一.Kruskal算法 Kruskal模板 二.Prim算法及堆优化 1.遍历 Prim 普通模板 2.堆优化 Prim 堆优化模板 解决最小生成树的问题之前,我们先 ...

  5. 生成top图_最小生成树(Kruskal和Prim算法)

    文章和资源同步更新至微信公众号:算法工程师之路 8月份会开启每日算法题系列,值得期待哦 上一篇文章,我们讲了图的创建和遍历,其中遍历的算法主要有BFS(广度优先算法)和DFS(深度优先算法)两种,并且 ...

  6. prim算法_最小生成树(Kruskal和Prim算法)

    文章和资源同步更新至微信公众号:算法工程师之路 8月份会开启每日算法题系列,值得期待哦 上一篇文章,我们讲了图的创建和遍历,其中遍历的算法主要有BFS(广度优先算法)和DFS(深度优先算法)两种,并且 ...

  7. 【老生谈算法】matlab实现Kruskal避圈算法求最小生成树——Kruskal避圈算法

    基于MATLAB的Kruskal避圈算法求最小生成树 1.原文下载: 本算法原文如下,有需要的朋友可以点击进行下载 序号 原文(点击下载) 本项目原文 [老生谈算法]基于MATLAB的Kruskal避 ...

  8. Java实现最小生成树算法(Prim算法)

    Prim算法 Prim算法,每一步都会为一颗生长中的树添加一条边.一开始这棵树只有一个顶点,然后哦会向它添加V-1条边,每次总是将下一条连接树的顶点与不在树中且权重最小的边加入树中 实现 最小生成树的 ...

  9. 贪心算法prim算法

    普利姆算法(Prim): 算法思想基于顶点选择,通过维护两个点集,已选点集S和未选点集T,每次选择从S集映射到T集的最小代价边,适用于稠密图. 图解dis更新过程: 最短路径求解时,dis更新的都是以 ...

最新文章

  1. linux id 命令 显示用户id和组id信息
  2. html的input的id,请求[“inputId”]不能在cshtml上工作
  3. 2020-07-14 CVPR2020 i3DV论文讨论(4) 笔记
  4. k_means算法+python实现
  5. 查看使用yum安装的软件路径
  6. java 双冒号_Java 双冒号::是什么操作符?
  7. 数字和字符对照关系表常用(编码表)
  8. 干货 | 每天十亿级数据更新,秒出查询结果,ClickHouse在携程酒店的应用
  9. 2019中南大学考研计算机考试,2019年中南大学计算机考研经验分享(复试+真题)...
  10. LCM液晶显示模组是什么,液晶显示模块有几种类型呢
  11. MySQL数据库的管理工具
  12. Linux中怎么创建文件?
  13. CookieSession会话技术
  14. 技术干货 | 一文弄懂差分隐私原理!
  15. 基于at89c51单片机的led数字倒计时器设计c语言,基于AT89C51单片机的LED数字倒计时器设计1.docx...
  16. 802.11a/b/g/n无线协议详解 802.11 无线认证和加密有什么区别 开放系统
  17. text与utext的区别
  18. 【简历优化】项目经验问什么怎么写怎么答
  19. MATLAB在app中扫描串口并在下拉菜单中显示
  20. 关于RDP协议的分析(一) - Linux论坛 - 计世网论坛 - Powered by Discuz!

热门文章

  1. .NETCore中实现ObjectId反解
  2. leetcode 整数反转
  3. 【Day04】介绍防抖节流原理、区别以及应用,并用 JavaScript 进行实现
  4. 【Java】判断某值是否在数组中,使用Arrays类
  5. 【Linux】Aria2 一键安装管理脚本 BT\PT一键安装包
  6. 配置hosts快速访问GitHub
  7. google search console的使用
  8. 怎么钢枪_和平精英有战术钢枪和无脑冲有何区别?你们怎么看待这个问题
  9. python数码时钟代码_python实现简易数码时钟
  10. Python学习笔记之常用模块总结,持续更新...