C++刷题周记(五) 您所在的位置:网站首页 刷课时代码 C++刷题周记(五)

C++刷题周记(五)

2023-05-27 11:48| 来源: 网络整理| 查看: 265

目录

最小生成树

基础概念

应用场景

辨析最小生成树与最短路径

Prim算法

概念

代码模板

辨析Prim与Dijkstra

并查集

思路

Kruskal算法

概念

代码模板

两种方法的辨析

最小生成树 基础概念

图论中的最小生成树指的是:包含原图的所有节点(假设图的节点数为n,最小生成树的边数则为n-1),且所用边权值最小的一条路径。

ps:图中可能存在重边和自环,边权可能为负数

应用场景

要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。

其他不同的表达方式:城市群之间修建公路/铁路,局部区域岛屿联通修桥......

常用Prim/Kruskal这两种算法解决最小生成树问题。

辨析最小生成树与最短路径

最小生成树:把连通的图的所有顶点连起来路径之和最小的问题,即生成树路径总权值之和最小。

最短路:把两点之间路径最短。最短路只需要将连接起点到终点,其路径并不一定经过所有点,即图中可以有孤立点。而最小生成树要连接图中的每一个点,不能有孤立点。

Prim算法 概念

Prim算法 : 把所有点到 已连通集合 的距离dis设成∞ ,每次找到距离最小的点,加入到连通集合中,并用该点距离进行松弛操作,更新所有点到集合距离 dis[i]=min(dis[i],g[t][i]) 即:从图中任意找一个起点,每次循环均要找到当前距连通集合最近的点,直到所有点都加入连通集合。

代码模板

模板题:Acwing 858      该代码与朴素Dijkstra的板子相似,流程与思想也比较接近

// 稠密图用邻接矩阵 int g[N][N]; // 记录点至连通集合的距离 int dist[N]; // 结点是否在连通集合中 bool state[N]; // 与迪杰算法的区别 D中的松弛操作是更新到起始点的距离 // 而Prim是更新到集合S的距离 int prim(){ memset(dist,0x3f,sizeof dist); int res = 0; // 当i=0时 第一次循环 所取的t点一定为1 dist[1] = 0;// 起点的dist一定为0 从而无需在循环里特判 for(int i = 0; i < n; i++){ int t = -1; //*1 寻找已连通集合之外 距连通集合最近的点t for(int j = 1; j dist[j])){ t = j; } } // *2 状态更新,加入结果 // 当距离为INF,表示图中有不与集合连通的孤立点,此时肯定没有最小生成树 if(dist[t] == INF) return INF; res += dist[t]; state[t] = true; // *3 g[t][j]即为j至 刚加入连通集合中的点t 的距离 根据此进行松弛操作 for(int j = 1; j > n >> m; for(int i = 0; i < m; i++){ int a,b,w; cin >> a >> b >> w; edges[i] = {a,b,w}; } // 点的并查集初始化 for(int i = 1; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有