单源最短路问题 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值