标签:ctime vijos 意义 图论 mat 多次 ace 消息 一个
无向图最短路径问题,是图论中最经典也是最基础的问题之一。本题我们考虑一个有 $n$ 个结点的无向图 $G$。
$G$ 是简单完全图,也就是说 $G$ 中没有自环,也没有重边,但任意两个不同的结点之间都有一条带权的双向边。
每一条边的边权是非负实数,但我们并不知道每一条边的具体边权。
好消息是我们知道 $G$ 中任意两点最短路径的长度$d(i,j)$。且保证至少有一种边权的分配方案满足得到的带权图中$i$与$j$的最短路长度恰好是$d(i,j)$。
下面是留给你的任务:对于任意一对点$(i,j)$,希望你能找出来所有合法的边权分配方案中$i$和$j$之间边权的最大值。
本题中,每一组数据都有多次询问,每一次询问分别给出了一个无向图$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)$)。
对于每一次询问,若给定的图$G$有$n$个结点,则输出$n$行,每行有$n$个整数,描述了一个矩阵 $a$。矩阵的第$i$行第$j$列表示连接$i$和$j$的边的最大可能边权。如果$(i,j)$的边权可以任意大,则输出字符串infty表示无限。
矩阵的对角线没有实质性意义,请全输出$0$。因为$G$是无向图,所以输出的矩阵$a$应该也是对称的(即$a(i,j)=a(j,i)$)。
不难发现,因为给定的矩阵 $d$ 中每一个数字都是整数,所以最大可能边权总会是整数。
2
3
0 2 8
2 0 10
8 10 0
3
0 1 1
1 0 1
1 1 0
0 2 8
2 0 infty
8 infty 0
0 1 1
1 0 1
1 1 0
对于 $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 }
标签:ctime vijos 意义 图论 mat 多次 ace 消息 一个
原文地址:http://www.cnblogs.com/NaVi-Awson/p/7663455.html