poj1860_bellman ford

题目描述:

   还是货币兑换的题,想找是否货币经过无数次兑换后是否会升值。兑换边符合(兑换货币值-兑换费用)*兑换率。

 

解题思路:

   典型的bellman ford。但是忘了。。。。

   复习下bellman-ford

首先是带负权值边的图,对于这样的图,如果存在负权回路是没法用djs等求最短路径的,因为每次更新不能确定的最短路径的点(可能由其他大权值的边+一条负权值的边重新更新得到更小)。

那么,对于包含复权回路的图,如何判断一个图是否存在负权回路能否计算出最短路径呢?bellman-ford就是解决介个问题滴。

判断方式就是:
我们知道如果这个图不存在负权回路的话,每做一次全部边的松弛操作(松弛操作就是判断 src->j 的长度是否大于 src->i+i->j的长度),是可以确定至少一个点的(因为只要没负权回路,就是指存在最短路径的说法,那么因为存在一个原始的出发点作为当前最短,肯定松弛过后肯定能有个点也达到了自己的最短情况)。
也就是说,如果做了n-1次的全部边松弛操作之后,就确定了所有点的最短路径值。如果做第n次全部边松弛操作的时候,还有点的最短值会被更新,则说明图里是存在负权回路的。

因此bellman ford算法是做n次边松弛操作,每次边松弛判断的是m条边。因此算法复杂度为O(nm)。

 

代码:

#include
#include
#define E 10001
#define N 101

typedef struct{
   int s, e;
   double w, c;
}EDGE;

int n,m,s;
double v, D[N];
EDGE edges[E];

main(){
   int i, j, flag;
  
   scanf(“%d %d %d %lf”, &n, &m, &s, &v);
   for(i=1;i<=m;i++){
      scanf(“%d %d %lf %lf %lf %lf”,&edges[2*i-1].s,&edges[2*i-1].e, &edges[2*i-1].w, &edges[2*i-1].c, &edges[2*i].w, &edges[2*i].c);
      edges[2*i].s = edges[2*i-1].e;
      edges[2*i].e = edges[2*i-1].s;
   }
   //memset(D,0,sizeof(D));
   for(i=1; i<=n; i++)
      D[i] = 0.0;
   D[s] = v;
  
   //bellman-ford
   for(i=1;i<=n;i++){
      flag = 0;
      for(j=1;j<=2*m;j++){ //遍历边做松弛操作
         double temp = (D[edges[j].s] – edges[j].c)*edges[j].w;
         if(D[edges[j].e] < temp){
         //if(D[edges[j].e] < (D[edges[j].s] – edges[j].c)*edges[j].w){ 
            flag = 1;
           // printf(“update %d. former = %lf, later = %lf\n”,edges[j].e, D[edges[j].e], (D[edges[j].s] – edges[j].c)*edges[j].w);
            D[edges[j].e] = (D[edges[j].s] – edges[j].c)*edges[j].w;
           
         }
      }
      if(0 == flag)
         break;
   }
  
   if(1 == flag){
      printf(“YES\n”);
   }else{
      printf(“NO\n”);
   }
  
   system(“pause”);
   return 0;
}

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