[Vijos 2024]无向图最短路径

Posted NaVi_Awson

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Vijos 2024]无向图最短路径相关的知识,希望对你有一定的参考价值。

Description

无向图最短路径问题,是图论中最经典也是最基础的问题之一。本题我们考虑一个有 $n$ 个结点的无向图 $G$。
$G$ 是简单完全图,也就是说 $G$ 中没有自环,也没有重边,但任意两个不同的结点之间都有一条带权的双向边。
每一条边的边权是非负实数,但我们并不知道每一条边的具体边权。
好消息是我们知道 $G$ 中任意两点最短路径的长度$d(i,j)$。且保证至少有一种边权的分配方案满足得到的带权图中$i$与$j$的最短路长度恰好是$d(i,j)$。
下面是留给你的任务:对于任意一对点$(i,j)$,希望你能找出来所有合法的边权分配方案中$i$和$j$之间边权的最大值。

Input

本题中,每一组数据都有多次询问,每一次询问分别给出了一个无向图$G$。
输入的第一行是一个整数 $t$,表示总共的询问个数。之后依次给出每一次询问。
对于每一次询问来说,第一行给出了 $G$ 中结点总数 $n$。之后$n$行每行有$n$个整数,给出了一个$n\times n$的矩阵 $d$,其中第$i$行第$j$列的整数对应 $d(i,j)$表示$i$到$j$的最短路径长度。
因为图$G$是简单无向图,对角线元素$d(i,i)$总是$0$,且矩形是对称的(也就是说$d(i,j)=d(j,i)$)。

Output

对于每一次询问,若给定的图$G$有$n$个结点,则输出$n$行,每行有$n$个整数,描述了一个矩阵 $a$。矩阵的第$i$行第$j$列表示连接$i$和$j$的边的最大可能边权。如果$(i,j)$的边权可以任意大,则输出字符串infty表示无限。
矩阵的对角线没有实质性意义,请全输出$0$。因为$G$是无向图,所以输出的矩阵$a$应该也是对称的(即$a(i,j)=a(j,i)$)。
不难发现,因为给定的矩阵 $d$ 中每一个数字都是整数,所以最大可能边权总会是整数。

Sample Input

2
3
0 2 8
2 0 10
8 10 0
3
0 1 1
1 0 1
1 1 0

Sample Output

0 2 8
2 0 infty
8 infty 0
0 1 1
1 0 1
1 1 0

HINT

对于 $20\%$ 的数据,有 $n = 3$。
对于 $50\%$ 的数据,有 $1\le n\le 10$。
对于 $100\%$ 的数据,有 $1\le n\le 100$,且所有询问中$n$的和不超过 $800$,对于所有的$d$满足$1\le d\le 256$。
每一组数据的时限为 $0.5$ 秒。

题解

这道题应该不难想吧...

我们把最短路边作为边权,还用类似$floyd$的过程,若存在$f[i][j] == f[i][k]+f[k][j]$,显然我$i<->j$这条边的边权可以为任意$>=f[i][j]$的值,显然就是$infty$;

若不存在,即只有这条边满足条件,边权不能比最短路大也不能小,那么就是原值。

 1 //It is made by Awson on 2017.10.13
 2 #include <set>
 3 #include <map>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <cmath>
 7 #include <stack>
 8 #include <queue>
 9 #include <vector>
10 #include <string>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <iostream>
15 #include <algorithm>
16 #define LL long long
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 #define Max(a, b) ((a) > (b) ? (a) : (b))
19 #define sqr(x) ((x)*(x))
20 using namespace std;
21 const int N = 100;
22 
23 int n, f[N+5][N+5];
24 bool judge[N+5][N+5];
25 
26 void work() {
27     scanf("%d", &n);
28     memset(judge, 0, sizeof(judge));
29     for (int i = 1; i <= n; i++)
30         for (int j = 1; j <= n; j++)
31             scanf("%d", &f[i][j]);
32     for (int k = 1; k <= n; k++)
33         for (int i = 1; i <= n; i++) if (i != k)
34             for (int j = 1; j <= n; j++) if (j != k && i != j)
35                 if (f[i][j] == f[i][k]+f[k][j]) judge[i][j] = 1;
36     for (int i = 1; i <= n; i++) {
37         for (int j = 1; j <= n; j++)
38             if (judge[i][j]) printf("infty ");
39             else printf("%d ", f[i][j]);
40         printf("\n");
41     }
42 }
43 int main() {
44     int t; scanf("%d", &t);
45     while (t--) work();
46     return 0;
47 }

 

以上是关于[Vijos 2024]无向图最短路径的主要内容,如果未能解决你的问题,请参考以下文章

教你一招 | Python实现无向图最短路径

C++ 不知图系列之基于链接表的无向图最短路径搜索

Python 图_系列之基于<链接表;实现无向图最短路径搜索

P4568 飞行路线分层图最短路

[图算法]多段图最短路径

数据结构与算法图最短路径算法 ( Floyed 算法 | 图最短路径算法使用场景 | 求解图中任意两个点之间的最短路径 | 邻接矩阵存储图数据 | 弗洛伊德算法总结 )