小明喜欢观景,于是今天他来到了蓝桥公园。
已知公园有 N 个景点,景点和景点之间一共有 M 条道路。小明有 Q 个观景计划,每个计划包含一个起点 st 和一个终点 ed,表示他想从 st 去到 ed。但是小明的体力有限,对于每个计划他想走最少的路完成,你可以帮帮他吗?
输入描述
输入第一行包含三个正整数 N,M,Q
第 2 到 M+1 行每行包含三个正整数 u,v,w,表示 u↔v 之间存在一条距离为 w 的路。
第 M+2M+2 到 M + Q-1M+Q−1 行每行包含两个正整数 st,edst,ed,其含义如题所述。
1\leq N\leq 4001≤N≤400,1\leq M \leq \dfrac{N\times(N - 1)}{2}1≤M≤2N×(N−1),Q\leq 10^3Q≤103,1\leq u,v,st,ed \leq n1≤u,v,st,ed≤n,1\leq w \leq 10^91≤w≤109
输出描述
输出共 Q 行,对应输入数据中的查询。
若无法从 st 到达 ed 则输出 −1。
输入输出样例
示例 1
输入
3 3 3
1 2 1
1 3 5
2 3 2
1 2
1 3
2 3
输出
1
3
2
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
思路:
如何求任意两点之间最短路径呢?通过之前的学习我们知道通过深度或广度优先搜索可以求出两点之间 的最短路径。所以进行 遍深度或广度优先搜索,即对每两个点都进行一次深度或广度优先搜索,便可 以求得任意两点之间的最短路径。可是还有没有别的方法呢?
Floyd算法 又称为弗洛伊德算法、插点法,是解决给定的加权图 中顶点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向 图的传递闭包。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特· 弗洛伊德命名。 ( )
算法核心:任意节点 到 的最短路径两种可能: 1.直接从 到 ; 2.从 经过若干个节点 到 ; 所以我们可以枚举每一个经过的点,对于任意节点 和 节点 , 从上面俩种中选择一条最小的路径进行更 新。
核心转移方程: dis[i][j] = min(dis[i][j] , dis[i][k] + dis[k][j]);
优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单 缺点:时间复杂度比较高,不适合计算大量数据。
时间复杂度:O(n^3) ;
空间复杂度:O(n^2) ;
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e3+10;
int dis[N][N];
void floyd(int n){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
signed main(){
int n,m,q;
int inf=1e15;
cin>>n>>m>>q;
memset(dis,0x3f,sizeof(dis));
while(m--){
int u,v;
long long w;
cin>>u>>v>>w;
dis[u][v]=dis[v][u]=min(dis[u][v] , w);
}
for(int i=1;i<=n;i++) dis[i][i]=0;
floyd(n);
while(q--){
int st,ed;
cin>>st>>ed;
if(dis[st][ed]>inf) cout<<-1<<endl;
else cout<<dis[st][ed]<<endl;
}
return 0;
}