【来源】
【题目描述】
给出一个有向图 G = ( V , E ) G=(V, E) G=(V,E),和一个源点 v 0 ∈ V v_0∈V v0∈V,请写一个程序输出 v 0 v_0 v0和图 G G G中其它顶点的最短路径。只要所有的有向环权值和都是正的,我们就允许图的边有负值。顶点的标号从 1 1 1到 n n n( n n n为图 G G G的顶点数)。
【输入格式】
第1行:一个正数 n ( 2 ≤ n ≤ 80 ) n(2≤n≤80) n(2≤n≤80),表示图G的顶点总数。
第2行:一个整数,表示源点 v 0 v_0 v0( v 0 ∈ V v_0∈V v0∈V, v 0 v_0 v0可以是图 G G G中任意一个顶点)。
第3至第 n + 2 n+2 n+2行,用一个邻接矩阵 W W W给出了这个图。
【输出格式】
共包含 n − 1 n-1 n−1行,按照顶点编号从小到大的顺序,每行输出源点 v 0 v_0 v0到一个顶点的最短距离。每行的具体格式参照样例。
【输入样例】
5
1
0 2 - - 10
- 0 3 - 7
- - 0 4 -
- - - 0 5
- - 6 - 0
【输出样例】
(1 -> 2) = 2
(1 -> 3) = 5
(1 -> 4) = 9
(1 -> 5) = 9
【提示】
样例所对应的图如下:
【解析】
这题的难点在于读入。
我们可以巧妙利用C/C++的优势:
if(scanf("%d",&a))
可以用于判断a是否是整数。
如果输入的是-
,自动返回-1
,而且scanf()
可以跳过空格。
读完后floyd就好了。
编Pascal的就没有那么幸运了。ヾ(•ω•`)o
【代码】
#pragma GCC optimize(3,"Ofast","inline")
#pragma G++ optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define RI register int
#define re(i,a,b) for(RI i=a; i<=b; i++)
#define ms(i,a) memset(a,i,sizeof(a))
#define MAX(a,b) (((a)>(b)) ? (a):(b))
#define MIN(a,b) (((a)<(b)) ? (a):(b))
using namespace std;
typedef long long LL;
int const N=105;
int const inf=0x3f3f3f;
int n,v;
int f[N][N];
int main() {
scanf("%d%d",&n,&v);
memset(f,inf,sizeof(f));
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
int a;
if(scanf("%d",&a)) f[i][j]=a;
else f[i][j]=inf;
}
for(int k=1; k<=n; k++) for(int i=1; i<=n; i++) for(int j=1; j<=n; j++)
f[i][j]=MIN(f[i][j],f[i][k]+f[k][j]);
for(int i=1; i<=n; i++) if(i!=v)
printf("(%d -> %d) = %d\n",v,i,f[v][i]);
return 0;
}