码迷,mamicode.com
首页 > 其他好文 > 详细

Bellman-Ford(可解决负权边)--时间复杂度优化

时间:2016-07-10 21:15:10      阅读:256      评论:0      收藏:0      [点我收藏+]

标签:

Bellman-Ford 可解决带有负权边的最短路问题

  解决负权边和Dijkstra相比是一个优点,Bellman-Ford的核心代码只有4行::

u[],v[],w[] 分别存一条边的顶点、权值,dis[]存从 1 源点到各个顶点的距离

技术分享

 

for(i=1;i<=n-1;i++)
    for(j=1;j<=m;j++)
        if(dis[v[i]] > dis[u[i]]+w[i])
            dis[v[i]] = dis[u[i]]+w[i];

 

 

  愿过程:

      循环n-1次,把每个顶点每条边都松弛;

     优化方法:

      ①,最坏的情况就是循环了n-1次才求出到每个顶点的最短路径,若果在n-1次之前就已经全部松弛完成,那么后面的循环就是多余

        优化:

for(k=1;k<=n-1;k++)//共有 n 个顶点,循环n-1次即可
{
        flag = 0;
        for(i=1;i<=m;i++)//对当前所有的边进行松弛
        {
            if(dis[v[i]] > dis[u[i]]+w[i])
            {
                dis[v[i]] = dis[u[i]]+w[i];
                flag = 1;
            }
        }
        if(flag == 0) break;//松弛也完成,结束
}

 

      ②,原过程:每次循环松弛过后,都有已经确定了的源点到某点最短的路径,此后这些顶点的最短路的值就会一直保持不变,不再受后续松弛操作的影响,但是每次还要判断是否需要松弛,这里浪费了时间。

     优化:确定一条边后总边数减一,把不能进行本次松弛的边再次后头存到原数组,松弛成功的边舍弃,再次松弛时只对未松弛的边进行操作,m的值会随着松弛预越来越小,直到全部完成。

for(k=1;k<=n-1;k++)//共有 n 个顶点,循环n-1次即可
    {
        m = M;//重新赋值后的 m 是数组中存储边的条数
        s = 1;flag = 0;
        for(i=1;i<=m;i++)//对当前所有的边进行松弛
        {
            if(dis[v[i]] > dis[u[i]]+w[i])
            {
                dis[v[i]] = dis[u[i]]+w[i];
                M--;    //松弛成功,边数减一
                flag = 1;
            }
            else//把本次不能进行松弛的边重新存储到当前的数组
            {
                u[s] = u[i];
                v[s] = v[i];
                w[s] = w[i];
                s++;
            }
        }
        if(flag == 0) break;//松弛也完成,结束
    }

附完整代码:

#include <stdio.h>
int main()
{
    int dis[10],i,k,m,n,s=1,u[10],v[10],w[10],M,flag;
    int inf = 99999999;
    scanf("%d%d",&n,&m);
    M = m;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u[i],&v[i],&w[i]);//输入各边及权值
    }
    for(i=1;i<=n;i++)
    {
        dis[i] = inf;//初始化为正无穷
    }
    dis[1] = 0;//以 1 为源点

    for(k=1;k<=n-1;k++)//共有 n 个顶点,循环n-1次即可
    {
        m = M;//重新赋值后的 m 是数组中存储边的条数
        s = 1;flag = 0;
        for(i=1;i<=m;i++)//对当前所有的边进行松弛
        {
            if(dis[v[i]] > dis[u[i]]+w[i])
            {
                dis[v[i]] = dis[u[i]]+w[i];
                M--;    //松弛成功,边数减一
                flag = 1;
            }
            else//把本次不能进行松弛的边重新存储到当前的数组
            {
                u[s] = u[i];
                v[s] = v[i];
                w[s] = w[i];
                s++;
            }
        }
        if(flag == 0) break;//松弛也完成,结束
    }

    for(i=1;i<=n;i++)
    {
        printf("%d ",dis[i]);
    }
    return 0;
}

 

 

 测试数据:

 5 5

  2 3 2

  1 2 -3

  1 5 5

  4 5 2

  3 4 3

运行结果:0 -3 -1 2 4

测试数据2:

   5 7

  1 2 2

  1 5 10

  2 3 3

  2 5 7

  3 4 4

  4 5 5

  5 3 6

运行结果:0 2 5 9 9

 

 

 

Bellman-Ford(可解决负权边)--时间复杂度优化

标签:

原文地址:http://www.cnblogs.com/ldy-miss/p/5658363.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!