All Pairs Shortest Path
Input
An edge-weighted graph G (V, E).
|V| |E|
s0 t0 d0
s1 t1 d1
:
s|E|-1 t|E|-1 d|E|-1
|V| is the number of vertices and |E| is the number of edges in G. The graph vertices are named with the numbers 0, 1,…, |V|-1 respectively.
si and ti represent source and target vertices of i-th edge (directed) and di represents the cost of the i-th edge.
Output
If the graph contains a negative cycle (a cycle whose sum of edge costs is a negative value), print
NEGATIVE CYCLE
in a line.
Otherwise, print
D0,0 D0,1 … D0,|V|-1
D1,0 D1,1 … D1,|V|-1
:
D|V|-1,0 D1,1 … D|V|-1,|V|-1
The output consists of |V| lines. For each ith line, print the cost of the shortest path from vertex i to each vertex j (j = 0, 1, … |V|-1) respectively. If there is no path from vertex i to vertex j, print “INF”. Print a space between the costs.
Constraints
1 ≤ |V| ≤ 100
0 ≤ |E| ≤ 9900
-2 × 107 ≤ di ≤ 2 × 107
There are no parallel edges
There are no self-loops
Sample Input 1
4 6
0 1 1
0 2 5
1 2 2
1 3 4
2 3 1
3 2 7
Sample Output 1
0 1 3 4
INF 0 2 3
INF INF 0 1
INF INF 7 0
Sample Input 2
4 6
0 1 1
0 2 -5
1 2 2
1 3 4
2 3 1
3 2 7
Sample Output 2
0 1 -5 -4
INF 0 2 3
INF INF 0 1
INF INF 7 0
Sample Input 3
4 6
0 1 1
0 2 5
1 2 2
1 3 4
2 3 1
3 2 -7
Sample Output 3
NEGATIVE CYCLE
Hint:
这是一个Floyd求最短路径问题,在此基础上增加了负环这一概念,需要掌握的知识有存图、Floyd算法和细心细心再细心。。。。。。
这个题在第11个测试点上连续WA了六次,Presentation Error了三次,正是因为这几个WA也让我免去了后边测试点的WA,还是多亏了小伙伴,帮我看代码共同找出了问题。
题意: 输入n个点和m条边(点从0开始到n - 1),在接下来m行输入每条边的起点、终点、和路径长度,注意是有向图。
- 注意路径的长度 -2 × 107 ≤ di ≤ 2 × 107 所以这里 要用long long 类型。
- 注意输出格式:每一行之后都有换行符,每一行中,除了第一个,其余每个数据之前都有一个空格。
- INF不要用0X3F3F3F,而是用 看代码。
- 敲黑板 划重点:我在输出"INF"时判断条件是: if(dis[i][j] == INF),然而当路径很多时在这个判断语句中会出问题:
if(dis[i][j] > dis[i][k] + dis[k][j])
dis[i][j] = dis[i][k] + dis[k][j];
如图,我们可以发现,9个INF的和就会小于INF了,我们主函数的判断语句就会失效。所以我们要做的更改是判断 如果在 i → k → j 的这条路径上只要有个距离等于了INF那么就要停止此次寻找。(而且伙伴说加了这个判断还可以减少一些不必要的运行过程,可能可以加快点速度呢,可知她看待时间有多扣多节约呢)。
还有一点:判断负环要在Floyd函数中进行判断,当某两点的距离为负数时,使flag标记变量变为0 。方便在主函数中进行判断是否要输出 NEGATIVE CYCLE\n" 。其他详情请看代码:
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100 + 10;
const int M = 10000;
const ll INF = 1LL<<32;
int n, m, flag = 1;
ll dis[N][N];
// 初始化邻接矩阵
void init(int n){
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
dis[i][j] = INF;
}
dis[i][i] = 0;
}
}
void Floyd(){
for(int k = 0; k < n; k ++){
for(int i = 0; i < n; i ++){
if(dis[i][k] == INF) continue;
for(int j = 0; j < n; j ++){
if(dis[k][j] == INF) continue;
if(dis[i][j] > dis[i][k] + dis[k][j])
dis[i][j] = dis[i][k] + dis[k][j];
}
if(dis[i][i] < 0){
flag = 0;
}
}
}
}
int main(){
int a, b, x;
scanf("%d %d", &n, &m);
init(n);
for(int i = 0; i < m; i++){
scanf("%d %d %d", &a, &b, &x);
dis[a][b] = x;
}
Floyd();
if(flag == 0){
printf("NEGATIVE CYCLE\n");
return 0;
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(j) printf(" ");
if(dis[i][j] == INF){
printf("INF");
}
else
printf("%lld", dis[i][j]);
}
printf("\n");
}
return 0;
}