Aizu - GRL_1_C All Pairs Shortest Path、Floyd、负环:【题解】

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行输入每条边的起点、终点、和路径长度,注意是有向图。

  1. 注意路径的长度 -2 × 107 ≤ di ≤ 2 × 107 所以这里 要用long long 类型
  2. 注意输出格式:每一行之后都有换行符,每一行中,除了第一个,其余每个数据之前都有一个空格。
  3. INF不要用0X3F3F3F,而是用 看代码。
  4. 敲黑板 划重点:我在输出"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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值