【C++】「一本通 3.4.2 练习 3」最短路径(shopth)

【来源】

一本通-1378

【题目描述】

给出一个有向图 G = ( V , E ) G=(V, E) G=(V,E),和一个源点 v 0 ∈ V v_0∈V v0V,请写一个程序输出 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) n2n80,表示图G的顶点总数。

第2行:一个整数,表示源点 v 0 v_0 v0 v 0 ∈ V v_0∈V v0V v 0 v_0 v0可以是图 G G G中任意一个顶点)。

第3至第 n + 2 n+2 n+2行,用一个邻接矩阵 W W W给出了这个图。

【输出格式】

共包含 n − 1 n-1 n1行,按照顶点编号从小到大的顺序,每行输出源点 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值