最短路之和
最短路之和
给定一个 个点的加权有向图,点的编号为 。
图中任意两点之间都有两条方向相反的边连接两点。
从点 到点 的边的长度为 。
给定一个 的排列 。
你需要对该图依次进行 个操作。
其中,第 个操作是将点 以及该点的所有入边和出边从图中移除。
在执行每一个操作之前,你还需要进行如下计算:
- 对于每个当前剩余点对 ,计算从点 到点 的最短路长度。
- 将这些最短路长度全部相加得到最短路之和。
注意:
- 剩余点对 :两个还未被移除的点 ()组成的点对。
- 和 是两个不同点对,需分别计算最短路长度并计入最短路之和。
- 个操作是按顺序依次执行的,前面的操作会对后面的计算产生影响。
请你输出执行每个操作前计算得到的最短路之和。
输入格式
第一行包含整数 。
接下来 行,每行包含 个整数,其中第 行第 个数为 。
最后一行包含 个整数 。
输出格式
共一行,输出 个整数,其中第 个整数表示执行第 个操作之前,计算得到的最短路之和。
数据范围
前 个测试点满足 。
所有测试点满足 ,,,,保证 是一个 的排列。
输入样例1:
1 0 1
输出样例1:
0
输入样例2:
2 0 5 4 0 1 2
输出样例2:
9 0
输入样例3:
4 0 3 1 1 6 0 400 1 2 4 0 1 1 1 1 0 4 1 2 3
输出样例3:
17 23 404 0
解题思路
比赛的时候猜对了做法,这题本质就是考对Floyd算法原理的理解。
因为这题要求任意两点间的最短路径,所以首先容易想到用Floyd。然后就是每次从点集中删除一个点,求点集中剩余点的任意两点间的最短距离的总和。删点的话不好做,那么试试倒过来做行不行。就是一开始点集为空,然后每次往点集中加入一个点(以及对应的边),再求点集中任意两点最短路。如果了解Floyd算法的原理的话那么就会知道,当第一层循环枚举完,此时求得的是任意两点间只经过节点编号的最短距离。因此每次我们当我们枚举到,那么就可以求出任意两点间只经过前个点的最短距离,而前个点就是我们往点集中加的前个点。
下面补个Floyd的推导过程,其实本质就是个dp。
定义状态表示所有从出发,最终走到,且中间只经过节点编号不超过的所有路径,属性就是路径长度的最小值。根据的路径中(不包含起点和终点)是否包含节点来划分集合。
- 如果的路径不包含节点,那么意味着当前的所有路径中只含有节点,对应的集合就是。
- 如果如果的路径包含节点,那么有,其中和的路径中只含有节点,分别对应的集合为和。
对这两种情况取最小值,那么就有状态转移方程
然后就是证明把状态定义的第一维去掉得到的与原本的状态是等价的。
当时,原本有,由于(初始化的时候有,即到本身的最小距离为),因此得到。因此对于的情况去掉第一维不会影响结果,因为状态存的是上一层的的结果。
同理当时,原本有,由于,因此得到。因此对于的情况去掉第一维不会影响结果,因为状态存的是上一层的的结果。
对于一般的,有
因此去掉第一维可以发现,与之前的状态转移方程是等价的。
因此状态转移方程就可以写成
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const int N = 510; 7 8 LL g[N][N]; 9 int p[N]; 10 LL ans[N]; 11 12 int main() { 13 int n; 14 scanf("%d", &n); 15 for (int i = 1; i <= n; i++) { 16 for (int j = 1; j <= n; j++) { 17 scanf("%lld", &g[i][j]); 18 } 19 } 20 for (int i = 1; i <= n; i++) { 21 scanf("%d", p + i); 22 } 23 for (int k = n; k; k--) { // 倒序插入点,求只经过p[k]~p[n]的最短路径 24 for (int i = 1; i <= n; i++) { 25 for (int j = 1; j <= n; j++) { 26 g[i][j] = min(g[i][j], g[i][p[k]] + g[p[k]][j]); 27 } 28 } 29 for (int i = n; i >= k; i--) { // 只统计已加入的点的结果 30 for (int j = n; j >= k; j--) { 31 ans[k] += g[p[i]][p[j]]; 32 } 33 } 34 } 35 for (int i = 1; i <= n; i++) { 36 printf("%lld ", ans[i]); 37 } 38 39 return 0; 40 }
参考资料
AcWing 4872. 最短路之和(AcWing杯 - 周赛):https://www.acwing.com/video/4653/
3.2 floyd算法及其扩展应用:https://www.acwing.com/file_system/file/content/whole/index/content/147349/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17208630.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-03-12 动态规划部分题集解