【公交路线——bellmanford】

本文介绍了如何使用Bellman-Ford算法解决含有负权重的有向图的单源最短路径问题,以设计一条从城市东站到西站的最短公交线路。通过实例解析了算法的运作过程,并提供了AC代码实现。需要注意的是,Bellman-Ford算法不能处理含有负权重回路的图,并且通常进行n-1次迭代以确保找到最短路径。
摘要由CSDN通过智能技术生成

公交路线


题目描述

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];
}

Bellman-Ford算法是一种用于计算单源最短路径的图算法,能够处理包含负权重边的图,但不能处理存在负权重环的图。该算法基于动态规划的思想,逐步放松图中的每一条边,直到达到最短路径。以下是使用MATLAB实现Bellman-Ford算法的基本步骤: 1. 初始化:将源点的距离设置为0,其他所有顶点的距离设置为无穷大。 2. 遍历所有边:对于图中的每一条边,尝试对每一条边的起点和终点进行更新操作,如果终点的距离可以被起点的距离加上边的权重减小,则更新终点的距离。 3. 检查负权重环:再次遍历所有边,如果仍然可以减少任何边的终点的距离,则说明图中存在负权重环。 4. 输出结果:如果没有发现负权重环,则算法结束,输出每个顶点的最短路径。 以下是MATLAB代码的一个简单示例: ```matlab function [distances, predecessors] = bellman_ford(graph, source) numVertices = size(graph, 1); distances = inf(1, numVertices); distances(source) = 0; predecessors = zeros(1, numVertices); % 遍历所有边 |V|-1 次 for i = 1:numVertices-1 for j = 1:numVertices for k = 1:numVertices if graph(j, k) < inf && distances(j) + graph(j, k) < distances(k) distances(k) = distances(j) + graph(j, k); predecessors(k) = j; end end end end % 检查负权重环 for j = 1:numVertices for k = 1:numVertices if graph(j, k) < inf && distances(j) + graph(j, k) < distances(k) error('Graph contains a negative-weight cycle.'); end end end end ``` 注意:这段代码并没有进行详尽的错误检查和优化,仅供参考。在实际应用中,可能需要根据具体问题进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值