单源最短路与bellmanford

单源最短路问题,就是对一个边带权图G和其上一点s,求G上每一点到s的权最小路


性质: 1.最短路上不会有环

            2.将达不到或者暂时达不到的点的距离习惯记做无穷

            3.该问题满足最优子结构,即最短路的子图也为最短路


如何记录:对每个节点v,维护一个值v.pi,表示这个点的前驱节点。求解完成之后使用他构造最短路径树即可、


基本操作:

       最短路径估计:对每个点维护一个值v.d,为当前估计的s到他的距离

       初始化:将所有v.d置为无穷,v.pi置为null

       松弛:对点u,v,若我们已经求出了u的最短路,且u,v邻接,对比u.d+w(u+v)和v.d,若v.d比较大,说明从u到达v比v当前认为的最短路更近,就可以将v.d置为u.d+w(u+v),将v.pi置为u


       之后的算法就基于松弛操作进行


bellmanford算法

能够解决带负权图的最短路问题,若图上有负权回路,返回false表示无解

    这个算法的思路比较暴力:每次把每条边松弛一次,重复v-1次。每次松弛完所有边后可以保证满足最短路性质的点距离原点的深度多了一层,所以重复v-1次后可以保证最短路已完成。

                  对于负权回路的判断:完成上面步骤后遍历一遍每条边,若还可以松弛,则说明有负权回路。

                  优化:如果某次操作中没有松弛,则说明之后也不会再松弛了,在这停止。

以hdu2544为例

//其实这题并没有用到bellmanford判负值的操作

#include <bits/stdc++.h>

using namespace std;
const int maxn=20000;
int vpi[200],vd[200],v,e;//前驱节点,最大值估计
struct edg
{
    int vs,ve,w;
}ed[maxn];
void init()
{
    memset(vpi,0,sizeof(vpi));
    int cs,ce,cw;
    for(int i=1;i<=v;i++) vd[i]=100000;
    vd[1]=0;
    for(int i=1;i<=e/2;i++)
    {

        cin>>cs>>ce>>cw;
        ed[i*2-1].vs=cs;
        ed[i*2-1].ve=ce;
        ed[i*2-1].w=cw;
        ed[i*2].vs=ce;
        ed[i*2].ve=cs;
        ed[i*2].w=cw;
    }

}
bool bellmanford()
{
    for(int i=1;i<=v;i++)
    {
        bool flag=true;
        for(int j=1;j<=e;j++)
        {
            if(vd[ed[j].ve]>vd[ed[j].vs]+ed[j].w)
            {
                vd[ed[j].ve]=vd[ed[j].vs]+ed[j].w;
                vpi[ed[j].ve]=ed[j].vs;
                flag=false;
            }
        }
        if(flag)break;
    }
    for(int i=1;i<=e;i++)
    {
        if(vd[ed[i].ve]>vd[ed[i].vs]+ed[i].w)
            return false;
    }
    return true;
}


int main()
{
    while(cin>>v>>e,v!=0)
    {
        e*=2;
        init();
        bellmanford();
        cout<<vd[v]<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值