Bellman_Ford ----->最短路

                                   

                                                               Bellman_Ford —–最短路


         情景带入:给你两个数 m,n。n代表一共有n个村庄,之后有m行,每行包含三个数 from,to,dist.这三个数代表着,从村庄from到村庄to有dist 这么长的距离,两个村庄之间可能有神奇的漩涡而导致他们之间的路径为负数。,此为无向图。

               现在想知道从村庄1到任意村庄的最短的路径是多少。


           可以想象,从村1到村n如果存在最短路,那么这个最短路之间的村庄数肯定是小于等于  n-1 的(包含村n),那么可以对输入的这m组数据关系,进行n-1次优化操作,那么得到的结果肯定就是最优的.


附代码:

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<iostream>
#include<string.h>
using namespace std;
const int inf=0x3f3f3f3f;
int main()
{
    int m,n;
    while(~scanf("%d%d",&m,&n))
    {
        int dist[n+3],fro[m+3],to[m+3],w[m+3];
        memset(dist,inf,sizeof(dist));
        dist[1]=0;
        for(int i=0; i<m; i++)
            scanf("%d%d%d",&fro[i],&to[i],&w[i]);

        for(int i=0; i<n-1; i++)
            for(int j=0; j<m; j++)
            {
                int x=fro[j],y=to[j];
                /*优化操作,与floyd相似,因为是无向图,所以需要用dist[x]
                来优化dist[y],并用dist[y]来优化dist[x]*/
                if(dist[x]<inf)
                    dist[y]=min(dist[y],dist[x]+w[j]);
                if(dist[y]<inf)
                    dist[x]=min(dist[x],dist[y]+w[j]);
            }
        printf("%d\n",dist[n]);
    }
}

     题目链接:http://poj.org/problem?id=2387


     此问题与http://blog.csdn.net/stffer/article/details/46834343的问题背景一样,可参考.


    由于还没做到合适的题目,所以就拿一个没有负数的最短路题目凑数了,但是bellman_frod是可以解决某些路径为负的最短路问题的,他们之间的最短路问题的.dijkstra不能解决是因为如果有负数存在,dijkstra算法每次都可以通过这个负数来更新出一个比之前数值更小的dist[]数组.于是就成了死循环了.而 bellman_frod 只执行(n-1)*m次优化操作.由于不存在负权,上述代码中也就没有判断是否存在负权回路


如有负权,应加上如下代码:

int flog==1;
                for(int i=0;i<m;i++)
                {
                    //不可能发生的情况,因为如果有最短路,那么最坏的结果也应该是
                    //dist[fro[i]]>dist[to[i]]+w[i]   或  dist[to[i]]>dist[fro[i]]+w[i]
                    if(dist[fro[i]]>dist[to[i]]+w[i])
                        {
                            flog=0;
                            break;
                        }
                    if(dist[to[i]]>dist[fro[i]]+w[i])
                    {
                        flog=0;
                        break;
                    }
                }
                if(flog==1) //无负权回路,即存在最短路
                else  //有负权回路


    说到bellman_frod 不得不说一下 SPFA,即用队列对现在的这一算法进行优化,思想还是不变的.

    附代码:


  

#include<stdio.h>
#include<algorithm>
#include<queue>
#include<iostream>
#include<string.h>
using namespace std;
const int inf=0x3f3f3f3f;
struct edge
{
    int to,w;
    edge(int to1=0,int w1=0):to(to1),w(w1) {}
};
vector<edge> G[10000];
void into(int fro,int to,int w)
{
    //无向图
    G[fro].push_back(edge(to,w));
    G[to].push_back(edge(fro,w));
}
int main()
{
    int m,n;
    while(~scanf("%d%d",&m,&n))
    {
        int dist[n+3],fro[m+2],to[m+2],w[m+2];
        int vist[n+3],cnt[n+3];
        queue<int>q;
        memset(vist,0,sizeof(vist));
        memset(cnt,0,sizeof(cnt));
        memset(dist,inf,sizeof(dist));
        dist[1]=0;
        vist[1]=1;
        for(int i=0; i<m; i++)
            scanf("%d%d%d",&fro[i],&to[i],&w[i]);
        for(int i=0; i<m; i++)  //初始化
            into(fro[i],to[i],w[i]);
        q.push(1);
        int flog=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vist[u]=0;
            for(int i=0; i<G[u].size();i++)
            {
                edge &ff=G[u][i];
                if(dist[u]<inf&&dist[ff.to]>dist[u]+ff.w)
                {
                    dist[ff.to]=dist[u]+ff.w;
                    if(vist[ff.to]==0)
                    {
                        q.push(ff.to);
                        vist[ff.to]=true;
                        if(++cnt[ff.to]>n)
                          {
                              flog=1;
                              break;
                          }
                    }
                }

            }
        }
       if(flog!=1) //存在最短路
        printf("%d\n",dist[n]);
    }
}





    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/stffer/article/details/46858139
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞