最短路,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;
}
望穿寂夜晨曦至,雄鹰展翅图九天。

浙公网安备 33010602011771号