最短路,Floyd | 洛谷 P1346 电车

题目传送门

题意

有一个 \(N\) 个点的有向图,每个点都连接着若干条边(可能有环)。每个点默认只能指向输入的第一个点,去其他点就需要将路程 \(+1\)
请写一个程序,计算点 \(A\) 到点 \(B\) 的最短路径。若无法从 \(A\) 前往 \(B\),输出 \(−1\)

分析

Floyd 算法是用来求图中任意两个结点之间的最短路的。实现方法如下:

  • 定义
    我们定义一个数组 dis[x][y],表示 \(x\)\(y\) 的最短路长度。
  • 初始化

    \[dis[u][v] = \begin{cases} w_{u, v} & (u, v) \in E \\ 0 & u = v \\ inf & \text{Otherwise.}\end{cases} \]

  • 转移
    每次找一个中转点 \(k\),再对每一组 \(x, y\) 的最短路进行松弛操作。
    dis[x][y] = min(dis[x][y], dis[x][k] + dis[k][y])
  • 复杂度
    时间复杂度为 \(O(n^3)\),空间复杂度为 \(O(n^2)\)

本题可以用 Floyd 算法求解。过程如下:

  • 初始化 \(dis\) 数组。
  • 读入存图(邻接矩阵),注意在此题中,只有每个点到输入的第一个点的 \(dis\) 值才为 \(0\),其它出边为 \(1\)
  • 跑一遍 Floyd 算法,求出每两个点之间的最短路径。
  • 输出答案,注意若求得答案为 \(inf\),则说明没有路径,要按题意输出 \(-1\)

代码

#include<bits/stdc++.h>
using namespace std;

const int inf = 1e9;
int n, s, t, k, x, dis[105][105];

inline void init()
{
    for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        dis[i][j] = inf, dis[i][i] = 0;
}

inline void Floyd()
{
    for(int k = 1; k <= n; k++)
    for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
    return;
}

int main()
{
	ios :: sync_with_stdio(false);
	cin >> n >> s >> t;
    init();
    for(int i = 1; i <= n; i++)
    {
        cin >> k;
        for(int j = 1; j <= k; j++)
        {
            cin >> x;
            dis[i][x] = !(j == 1);
        }  
    }
    Floyd();
    cout << (dis[s][t] == inf ? -1 : dis[s][t]);
	return 0;
}
posted @ 2023-07-02 17:05  心灵震荡  阅读(59)  评论(0)    收藏  举报