公交路线
题目描述
P市有n个公交站,之间连接着m条道路。P市计划新开设一条公交线路,该线路从城市的东站(s点)修建到西站(t点),请为P市设计一条满足上述条件并且最短的公交线路图。
输入描述:
第一行有4个正整数n,m,s,t。
接下来m行,每行3个数a,b,v描述一条无向道路a——b,长度为v。
输出描述:
如果有解,输出一行,表示满足条件的最短公交线路的长度c。
否则,输出“-1”
示例:
示例1
输入
3 3 1 2
1 2 3
2 3 4
1 3 5
输出
3
示例2
输入
3 3 1 2
1 2 5
2 3 3
1 3 1
输出
4
示例3
输入
3 1 1 1
1 2 1
输出
0
备注:
对于100%的测试数据:
1 ≤ s,t ≤ n ≤ 1000
1 ≤ m ≤ 10000
1 ≤ 道路的长度 ≤ 10000
说明
单纯只是为了写个bellmanford的板子。
关于bellmanford:
它是为了求解含负权边的带权有向图的单源最短路径问题,它是由贝尔曼和福特提出的从源点依次绕过其他顶点,以缩短到达终点的最短路径长度。不能处理带负权的无向图。算法的结果是为了求出从源点到其他点的最短路径。
bellmanford的限制条件:
要求图中不能包含权值总和为负值的回路(负权值回路)
关于n-1次循环的说明:
比如一组数据:
6 10 1 6
1 2 3
1 5 1
1 4 4
1 6 9
2 3 4
4 6 3
4 3 2
5 3 2
5 2 1
6 3 1
这样给出的话一个循环就能求出源点到其他点的最短路径,即以谁为源点,谁的邻边就要先给出。
6 10 1 2
4 3 2
2 3 4
4 6 3
1 2 3
6 3 1
5 2 1
1 5 1
1 4 4
5 3 2
1 6 9
这样给出就不行。
AC代码:
代码如下:
#include<iostream>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1005;
int n,m,s,t,dis[N];
struct node{
int st,to,va;
};
vector<node> v1;
void bellman_ford(int s){
for(int i=1;i<=n;++i)
dis[i]=INF; //初始化,假定源点与其他点都不联通
dis[s]=0;
for(int i=1;i<n;++i)//因为不确定存边顺序,所以最保险用n-1个大循环,理论上1个循环就可能得到源点到其他所有点的最短路径,所以这也造成了很多重复的步骤,所以也就有了SPFA。
for(int j=0;j<2*m;++j){
//1.因为是无向图,所以有2m条边
//2.一轮循环可以确定一个点与其他点的最短距离
//3.因为初始化dis[s]=0,则第一轮就能确定s与s直接相连的点的最短距离
//4.接下来的循环则是以已经确定最短路的点作为中转点去更新其他点
int u=v1[j].st,v=v1[j].to,w=v1[j].va;
if(dis[v]>dis[u]+w) //以u作为中转点
dis[v]=dis[u]+w;
}
}
int main(){
cin>>n>>m>>s>>t;
int a,b,v;
for(int i=0;i<m;++i){
cin>>a>>b>>v;
v1.push_back({a,b,v});
v1.push_back({b,a,v});
}
bellman_ford(s);
if(dis[t]>INF/2)
cout<<"-1";
else
cout<<dis[t];
}