文章目录
前言:在求任意两点间的最短路问题中,图一般较为稠密,使用Floyd算法可以在O(N ^ 3)的时间实现。当然也可以把每个点作为起点,求解N次单源最短路径问题,但较为复杂。这里介绍Floyd算法以及使用Floyd算法打印路径和解决选址问题
算法分析
假设用d[k, i, j]表示“经过若干编号不超过k的结点”从i 到 j的最短路长度,这个问题可以划分为两个子问题,经过编号不超过 k - 1 的结点从i到j或者从i 先到k ,再到j,所以有:
d[k, i, j] = min(d[k - 1, i, j], d[k - 1, i, k] + d[k - 1, k, j])
因为一般解决稠密图,所以使用邻接矩阵。
Floyd算法的本质是动态规划,k表示我们所划分的阶段,所以在循环的最外层,但我们写的时候已经将其优化,像背包问题等动态规划中那样,使用“滚动数组”优化。
所以才有: d[i][j] = min(d[i][j] , d[i][k] + d[k][j]);
Floyd裸模板
给定一个n个点m条边的有向图,图中可能存在重边和自环,边权可能为负数。
再给定k个询问,每个询问包含两个整数x和y,表示查询从点x到点y的最短距离,如果路径不存在,则输出“impossible”。
数据保证图中不存在负权回路。
输入格式
第一行包含三个整数n,m,k
接下来m行,每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。
接下来k行,每行包含两个整数x,y,表示询问点x到点y的最短距离。
输出格式
共k行,每行输出一个整数,表示询问的结果,若询问两点间不存在路径,则输出“impossible”。
数据范围
1≤n≤200,
1 ≤ k ≤ n2
1 ≤ m ≤20000
图中涉及边长绝对值均不超过10000。
输入样例:
3 3 2
1 2 1
2 3 2
1 3 1
2 1
1 3
输出样例:
impossible
1
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 210, INF = 1e9;
int n, m, q;
int d[N][N];
void flody()
{
for(int k = 1; k <= n; k ++ )
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= n; j ++ )
d[i][j] = min(d[i][j] , d[i][k] + d[k][j]);
}
int main()
{
cin >> n >> m >> q;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= n; j ++ )
if