单源最短路问题 bellman-ford算法

贴一个链接将最短路问题的:http://www.cnblogs.com/Yan-C/p/3916281.html

Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).

这个算法是基于动态规划的思想。也就是利用现在的最小路径去更新其他路径的最小距离。

有个要点就是要对边进行松弛操作,其实就是更新路径吧~

用dis数组来存储这个点到起点的最小距离。用一个struct来存储每一条边的信息。

算法步骤:

1、对图进行初始化,dis[]=INF , dis[s] = 0;s表示起点。

2、对于每一条边都进行n-1次的松弛操作,求取最短路径。

3、再对每一条进行一次的松弛操作,检查是否存在负环并返回相应的布尔值,因为进行|V|-1次松弛后若没有负环则v.d的值确定不变,若有负环则会继续进行松弛操作,因为一个数+负数是一定比它本身要小的。

一道例题 hdu 1874  还有就是对无向图的处理,可以转化成有向图的两个方向相同的权值。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 2009
#define INF 0x3f3f3f3f
struct
{
    int u,v,w; //u代表起点,v代表终点,w代表这条边之间的权值。
}edge[M];  //保存所有边
int dis[M];
int n,m;
void bellman_ford(int s)
{
    fill(dis,dis+n,INF);
    dis[s] = 0;
    m = m*2;
    for(int i = 1;i < n;i++)
    {
        bool flag = false;
        for(int j = 0;j < m;j++)
        {
            if(dis[edge[j].u]!=INF && dis[edge[j].v]>dis[edge[j].u]+edge[j].w)//松弛操作,(即更新每一个点的最短距离)
            {                                                                 //注意顺序不要搞错,如果终点的距离小于起点的距离加上这条边的权值就更新终点的距离
                dis[edge[j].v]=dis[edge[j].u]+edge[j].w;
                flag = true;
            }
        }
        if(!flag)break;
    }
    /*for(int j = 0;j < m;j++) //判断是否存在负圈
    {
        if(dis[edge[j].u]!=INF && dis[edge[j].v]>dis[edge[j].u]+edge[j].w)
            return  true;  //存在负圈
    }*/
}
int main()
{
    while(scanf("%d %d",&n,&m)==2)
    {
        for(int i = 0;i < m;i++)
        {
            scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
            edge[i+m].u = edge[i].v;  //小心!要交换起点和终点的位置 WA了好几次
            edge[i+m].v = edge[i].u;  //无向图的处理
            edge[i+m].w = edge[i].w;
        }
        int a,b;
        scanf("%d %d",&a,&b);
        bellman_ford(a);
        if(dis[b]==INF)
            printf("-1\n");
        else
            printf("%d\n",dis[b]);
    }
    return 0;
}


### Bellman-Ford算法单源短路问题的实现与分析 Bellman-Ford算法是一种用于解决单源短路问题的经典算法,能够处理带负权边的图。该算法的核心思想是通过松弛操作逐步更新从点到其他所有顶点的距离,直到达到优解。以下是关于Bellman-Ford算法的具体实现和分析[^1]。 #### 算法原理 Bellman-Ford算法的基本原理是基于动态规划的思想。它通过多执行 \(n-1\) 次松弛操作(其中 \(n\) 是图中顶点的数量),确保从点到所有顶点的短路径被正确计算。每次松弛操作都会遍历图中的所有边,并尝试更新当前已知的短路径距离。如果在第 \(n-1\) 次迭代后仍然可以更新某些顶点的距离,则说明图中存在负权环[^2]。 #### 算法实现 以下是Bellman-Ford算法的伪代码及其实现: ```python def bellman_ford(graph, source): # 初始化距离数组,将所有顶点的距离设为无穷大,点距离设为0 distance = {node: float('inf') for node in graph} distance[source] = 0 # 图中顶点数 n = len(graph) # 进行n-1次松弛操作 for _ in range(n - 1): for u in graph: for v, weight in graph[u]: if distance[u] + weight < distance[v]: distance[v] = distance[u] + weight # 检查是否存在负权环 for u in graph: for v, weight in graph[u]: if distance[u] + weight < distance[v]: raise ValueError("Graph contains a negative-weight cycle") return distance ``` #### 陈越与浙江大学的相关研究 陈越教授及其团队在浙江大学讲授的数据结构与算法课程中,对Bellman-Ford算法进行了深入讲解。课程中强调了Bellman-Ford算法的优势在于能够处理带有负权边的图,但其时间复杂度较高,为 \(O(n \cdot m)\),其中 \(n\) 是顶点数,\(m\) 是边数。因此,在实际应用中,若图中不存在负权边,通常会优先选择Dijkstra算法以提高效率。 此外,陈越教授还提到了Bellman-Ford算法的一种优化方法——队列优化(SPFA算法)。该方法通过维护一个队列来减少不必要的松弛操作次数,从而在大多数情况下显著提升性能[^2]。 #### 算法分析 Bellman-Ford算法时间复杂度为 \(O(n \cdot m)\),空间复杂度为 \(O(n)\)。尽管其时间复杂度较高,但它具有以下优势: 1. 能够处理带负权边的图。 2. 可以检测图中是否存在负权环。 然而,对于大规模稀疏图,Bellman-Ford算法可能显得效率较低。此时,可以考虑使用Dijkstra算法或其变种(如堆优化版)[^1]。 #### 示例应用 以下是一个具体的例子,展示如何使用Bellman-Ford算法求解单源短路问题。 假设图的邻接表表示如下: ```python graph = { 'A': [('B', 1), ('C', 4)], 'B': [('C', 2), ('D', 6)], 'C': [('D', 3)], 'D': [] } ``` 调用 `bellman_ford(graph, 'A')` 将返回从顶点 `'A'` 到其他所有顶点的短路径距离。 #### 注意事项 在实际应用中,需要特别注意图中是否存在负权环。若存在负权环,则无法计算出有效的短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值