题目分析


来源:acwing

分析: 这题是最短路树。保持原图中所有点到根结点的最短距离不变,然后在原图中选择一些边,使所有点连通的最短路是多长。

最短路径树,是一种使用最短路径算法生成的数据结构树。
定义
考虑一个连通无向图G,一个以顶点v为根节点的最短路径树T是图G满足下列条件的生成树——树T中从根节点v到其它顶点u的路径距离,在图G中是从v到u的最短路径距离。

来源:维基百科

在这个生成树上的两点a和b,如果a能通过b点到达根结点,那么有一个等式d[b]=d[a]+wa−>bd[b] = d[a] + w_{a->b}d[b]=d[a]+wa−>b​,其中d[b]d[b]d[b]和d[a]d[a]d[a]表示该点到根的距离,wa−>bw_{a->b}wa−>b​表示a到b的距离。

既然有了这个等式,其实每个点到根结点的路径的选项就有限了,因为该点到根的最小距离可以求出来,该点通过其他点到根结点一定满足上面的等式,所以我们可以预处理出来可行的通路!做法是dijkstra求每个点的最短路,然后遍历除根之外的所有点,看看它们的邻边有哪些是满足上面这个等式的。

其实,上面等式还说明了另一个问题,就是d[a] 一定比d[b]小,因为边权都是正的,这就启发我们将单源最短路的点从小到大排序,从小到大开始查看是否满足这个等式,满足的可以和根结点形成树!

我们假设f(i)表示把前i个点合法挂到根结点所需要的总代价。
在挂第i个点的时候,只有几个点满足上述等式(我们称之为备选边),
所以有 f(i)=min[f(i−1)+w(被选点→i)]f(i) = min[f(i-1) + w(被选点\rightarrow i)]f(i)=min[f(i−1)+w(被选点→i)]

到这一步,这里公共的是f(i-1),我们只需要求出最小的w(某点->i点)即可。

所以,我们最后求的答案就是不断从根的邻点遍历,求出每个点权值最小的边(该点需要满足d[b]=d[a]+wa−>bd[b] = d[a] + w_{a->b}d[b]=d[a]+wa−>b​这个等式)

所以,核心代码如下

for(int a = 2; a <= n; a ++){int minw = INF; // 遍历所有的邻点for(int j = h[a]; ~j; j = ne[j]){int b= e[j];if(dist[a] == dist[b] + w[j])minw = min(minw, w[j]);}res += minw; // 每个点找到权值最小的边}

AC代码

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 10010, M = 200010, INF = 0x3f3f3f3f;int dist[N];
bool st[N];int n, m;
int h[N], e[M],ne[M], w[M], idx;void add(int a, int b, int c){e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}// 求根到所有点的最短路
void dijkstra(){memset(dist, 0x3f, sizeof dist);dist[1] = 0;priority_queue<PII, vector<PII>, greater<PII>> heap;heap.push({0, 1});while(heap.size()){auto t = heap.top();heap.pop();int ver = t.y, distance = t.x;if(st[ver]) continue;st[ver] = true;for(int i = h[ver]; ~i; i = ne[i]){int j = e[i];if(dist[j] > distance + w[i]){dist[j] =  distance + w[i];heap.push({dist[j], j});}}}}int main(){cin >> n >> m;memset(h, -1, sizeof h);while(m --){int a, b, c;cin >> a >> b >> c;add(a, b, c), add( b, a, c);}dijkstra();// int res = 0;for(int a = 2; a <= n; a ++){int minw = INF;// 遍历所有的邻点for(int j = h[a]; ~j; j = ne[j]){int b= e[j];// 根到a的距离 == 根到b的距离 + a到b的距离if(dist[a] == dist[b] + w[j])minw = min(minw, w[j]);}res += minw;}cout << res << endl;
}

题目链接

CSP认证201609-4 交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想相关推荐

  1. PAT甲级1111 Online Map (30分):[C++题解]两次dijkstra求单源最短路、保存路径、长度最短、时间最短

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析:dijkstra求单源最短路的题目. 只是写两遍而已,第一遍求按照路径长度求,第二遍按照时间最少求. 另外加一个vector路径的判断 ...

  2. PAT甲级1131 Subway Map (30分):[C++题解]堆优化dijkstra、单源最短路、地铁地图、巧妙地建图套dijkstra模板!!

    文章目录 题目分析 题目链接 题目分析 原题: 来源:acwing 分析: 建图:所有能走到的点之间建立一条边,比如下面一条地铁线路有4站,它们是相通的,两两之间建一条边,边权是经过的站点数. 下面考 ...

  3. PAT甲级1087 All Roads Lead to Rome (30分):[C++题解]dijkstra求单源最短路综合、最短路条数、保存路径

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 首先这是一道dijkstra算法求最短路的题目,不过此题较为复杂.首先需要将字符串城市名映射成数字,这里使用hash table 名 ...

  4. PAT甲级1030 Travel Plan (30分):[C++题解]dijkstra求单源最短路、保存路径

    文章目录 题目分析 题目链接 题目分析 来源:PAT网站 分析 dijkstra模板默写过来,然后多了一个保存路径,使用数组pre[N]记录最短路上每个点的前驱,通过pre数组保存到vector中 v ...

  5. [AcWing算法提高课]之图论 单源最短路的综合应用(C++题解)

    目录 1)热浪(板子题) (朴素dijkstra) O(n2) (堆优化dijkstra) O((n+m)logm) (spfa) O(m) 2)信使 3)香甜的黄油 4)最小花费 5) 最优乘车 6 ...

  6. CSP认证201803-2 碰撞的小球[C++题解]:模拟

    文章目录 题目解答 题目链接 题目解答 来源:acwing 分析: 题目理解: 给定水平方向的线段和n个小球,给定速度和碰撞后反向运动等条件,模拟小球碰撞过程,求解最后时刻所有小球的位置. 题目解答: ...

  7. CSP认证201809-4 再卖菜[C++题解]:差分约束、前缀和

    文章目录 题目解答 题目链接 题目解答 来源:acwing 分析: 对于a0,a1,...,ana_0, a_1,...,a_na0​,a1​,...,an​,经过计算相邻的数的平均值得到b0,b1, ...

  8. CSP认证201712-4 行车路线[C++题解]:单源最短路变型、拆点、好题!

    文章目录 题目解答 题目链接 题目解答 来源:acwing 分析: 题目给定所有答案不超过1e6,其实也就保证了连续小路的长度不超过1000(1000的平方就是1e6).这样我们就可以在题目给定的条件 ...

  9. CSP认证201712-1 最小差值[C++题解]:遍历

    文章目录 题目解答 题目链接 题目解答 来源:acwing 分析: 直接排序,然后取相邻两数之差的最小值. ac代码 #include<bits/stdc++.h> using names ...

最新文章

  1. 《JavaScript面向对象精要》——1.8 原始封装类型
  2. IDC:企业向云转变推动了SD-WAN市场增长
  3. python3库_对python3中pathlib库的Path类的使用详解
  4. java 回收策略_Java堆回收策略
  5. forall oracle 游标,FORALL用法小结
  6. 软件版权的双重许可是什么
  7. gitlens突然不显示了_损失百万!预防LED显示屏火灾隐患,从三方面入手
  8. ARM中C和汇编混合编程及示例
  9. mail ru android,mail ru app下载
  10. 4-2日装饰器,带参数的装饰器
  11. [转载]如何将Putty生成的PrivateKey转换为SecureCRT所需的PublicKey
  12. Codeforces Round #735 (Div. 2)(A-D)没有B
  13. hamburger组件_一个侧边栏导航组件实现思路
  14. BZOJ1041:[HAOI2008]圆上的整点(数论)
  15. Linux安装教程4,pfSense-2.4.4安装教程
  16. 20130912计划
  17. 持续交付+springboot+k8s
  18. Mac 给新人的入手指南
  19. freeswitch 解决方案之视频会议
  20. cms免费建立java官网,免费开源cms

热门文章

  1. Scrapy练习——爬取京东商城商品信息
  2. Mybatis加入Ehcache支持
  3. 201521123091 《Java程序设计》第4周学习总结
  4. asp.net在线预览txt文件(简单实现)
  5. GARFIELD@02-17-2005
  6. 构造一个完美的分类系统
  7. 【控制】《自动控制原理》胡寿松老师-第2章-控制系统的数学模型
  8. STM32 基础系列教程 45 - FSMC_LCD_Touch
  9. STM32 基础系列教程 41 – SDMMC
  10. 安装中文版man手册,同时保留原英文版手册