首页 > 其他分享 >最短路之和

最短路之和

时间:2023-03-12 18:13:03浏览次数:39  
标签:right min int 短路 leq left

最短路之和

给定一个 $n$ 个点的加权有向图,点的编号为 $1 \sim n$。

图中任意两点之间都有两条方向相反的边连接两点。

从点 $i$ 到点 $j$ 的边的长度为 $a_{ij}$。

给定一个 $1 \sim n$ 的排列 $x_1,x_2, \ldots ,x_n$。

你需要对该图依次进行 $n$ 个操作。

其中,第 $i$ 个操作是将点 $x_i$ 以及该点的所有入边和出边从图中移除。

在执行每一个操作之前,你还需要进行如下计算:

  • 对于每个当前剩余点对 $(u,v)$,计算从点 $u$ 到点 $v$ 的最短路长度。
  • 将这些最短路长度全部相加得到最短路之和。

注意:

  • 剩余点对 $(u,v)$:两个还未被移除的点 $u,v$($u \ne v$)组成的点对。
  • $(u,v)$ 和 $(v,u)$ 是两个不同点对,需分别计算最短路长度并计入最短路之和。
  • $n$ 个操作是按顺序依次执行的,前面的操作会对后面的计算产生影响。

请你输出执行每个操作前计算得到的最短路之和。

输入格式

第一行包含整数 $n$。

接下来 $n$ 行,每行包含 $n$ 个整数,其中第 $i$ 行第 $j$ 个数为 $a_{ij}$。

最后一行包含 $n$ 个整数 $x_1,x_2, \ldots ,x_n$。

输出格式

共一行,输出 $n$ 个整数,其中第 $i$ 个整数表示执行第 $i$ 个操作之前,计算得到的最短路之和。

数据范围

前 $4$ 个测试点满足 $1 \leq n \leq 4$。
所有测试点满足 $1 \leq n \leq 500$,$1 \leq a_{ij} \leq {10}^{5}$,$a_{ii}=0$,$1 \leq x_i \leq n$,保证 $x_1 \sim x_n$ 是一个 $1 \sim n$ 的排列。

输入样例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算法的原理的话那么就会知道,当第一层循环枚举完$k$,此时求得的是任意两点间只经过节点编号$1 \sim k$的最短距离。因此每次我们当我们枚举到$k$,那么就可以求出任意两点间只经过前$k$个点的最短距离,而前$k$个点就是我们往点集中加的前$k$个点。

  下面补个Floyd的推导过程,其实本质就是个dp。

  定义状态$f(k,i,j)$表示所有从$i$出发,最终走到$j$,且中间只经过节点编号不超过$k$的所有路径,属性就是路径长度的最小值。根据$i \to j$的路径中(不包含起点$i$和终点$j$)是否包含节点$k$来划分集合。

  1. 如果$i \to j$的路径不包含节点$k$,那么意味着当前$i \to j$的所有路径中只含有节点$1 \sim k-1$,对应的集合就是$f(k-1,i,j)$。
  2. 如果如果$i \to j$的路径包含节点$k$,那么有$i \to \cdots \to k \to \cdots \to j$,其中$i \to \cdots \to k$和$k \to \cdots \to j$的路径中只含有节点$1 \sim k-1$,分别对应的集合为$f(k-1,i,k)$和$f(k-1,k,j)$。

  对这两种情况取最小值,那么就有状态转移方程$$f(k,i,j) = \min \left\{ {f(k-1,i,j),\ f(k-1,i,k)+f(k-1,k,j)} \right\}$$

  然后就是证明把状态定义的第一维$k$去掉得到的$f(i,j)$与原本的状态是等价的。

  当$j = k$时,原本有$f(k,i,k) = \min \left\{ {f(k-1,i,k),\ f(k-1,i,k)+f(k-1,k,k)} \right\}$,由于$f(k-1,k,k) = 0$(初始化的时候有$f(0,k,k) = 0$,即$k$到本身的最小距离为$0$),因此得到$f(k,i,k) = \min \left\{ {f(k-1,i,k),\ f(k-1,i,k)} \right\} = f(k-1,i,k)$。因此对于$j=k$的情况去掉第一维不会影响结果,因为状态$f(i,k)$存的是上一层的$f(i,k)$的结果。

  同理当$i = k$时,原本有$f(k,k,j) = \min \left\{ {f(k-1,k,j),\ f(k-1,k,k)+f(k-1,k,j)} \right\}$,由于$f(k-1,k,k) = 0$,因此得到$f(k,k,j) = \min \left\{ {f(k-1,k,j),\ f(k-1,k,j)} \right\} = f(k-1,k,j)$。因此对于$i=k$的情况去掉第一维不会影响结果,因为状态$f(k,j)$存的是上一层的$f(k,j)$的结果。

  对于一般的$f(k,i,j)$,有$$\begin{align*} f(k,i,j) &= \min \left\{ {f(k-1,i,j),\ f(k-1,i,k)+f(k-1,k,j)} \right\} \\  &= \min \left\{ {f(k-1,i,j),\ f(k,i,k)+f(k,k,j)} \right\} \end{align*}$$

  因此去掉第一维可以发现$f(i,j) = \min \left\{ {f(i,j),\ f(i,k)+f(k,j)} \right\}$,与之前的状态转移方程是等价的。

  因此状态转移方程就可以写成$$f(i,j) = \min \left\{ {f(i,j),\ f(i,k)+f(k,j)} \right\}$$

  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/

标签:right,min,int,短路,leq,left
From: https://www.cnblogs.com/onlyblues/p/17208630.html

相关文章

  • 最短路径算法
    原理1.算出目前数据中,起点到终点的最短路径2.路径从短到长获取目前最短的路径,设置标识,有标识的不参与下一步循环 packagecom.jason.base.arithmetic;importlom......
  • dijkstra 建立虚拟源点求最短路
    题目:有N个村庄,编号1到N。村庄之间有M条无向道路,第i条道路连接村庄ai和村庄bi,长度是ci。所有村庄都是连通的。共有K个村庄有商店,第j个有商店的村庄编......
  • 最短路
    概述最短路算法主要研究图上两点之间的最短路径问题。事实上,许多问题都能转化为图来求解(图的本质就是点和边的集合,点是元素,边是元素之间的二元关系)。所以最短路算......
  • 最短路问题
    最短路问题图论中求某点到某点最短的路径长度。图中点1到点4的最短路径长度应为3.分类最短路问题分为两类:单源最短路和多源最短路。前者只需要求一个固定的起点到各个......
  • Johnson 全源最短路 学习笔记
    我居然不会这玩意,过来学一下。算法简介Johnson全源最短路用于求一个带负权的图的任意两点之间的最短路,时间复杂度为\(\Theta(nm\logm)\)。算法流程考虑到\(n\)次......
  • hihoCoder 1081 : 最短路径·一
    #1081:最短路径·一10000ms1000ms256MB描述万圣节的早上,小Hi和小Ho在经历了一个小时的争论后,终于决定了如何度过这样有意义的一天——他们决定去闯鬼屋!在鬼屋门......
  • hihoCoder 1089 : 最短路径·二:Floyd算法
    #1089:最短路径·二:Floyd算法10000ms1000ms256MB描述万圣节的中午,小Hi和小Ho在吃过中饭之后,来到了一个新的鬼屋!鬼屋中一共有N个地点,分别编号为1..N,这N个地点之......
  • 图的最短路径算法
    1.不带权值的最短路径对于不带权值的最短路径而言,我们可以采用广度优先遍历的方法,同时在遍历的过程中记录其上一个节点即可。如下图所示,我们找寻从A顶点到H顶点的最短......
  • E. Nearest Opposite Parity(多源最短路bfs)
    题目NearestOppositeParity(多源最短路bfs)题意思路多源最短路代码constintN=2e5+10;inta[N];vector<int>edge[N];intdist[N];intans[N];voidbf......
  • Til the Cows Come Home ( POJ 2387) (简单最短路 Dijkstra)
    problemBessieisoutinthefieldandwantstogetbacktothebarntogetasmuchsleepaspossiblebeforeFarmerJohnwakesherforthemorningmilking.......