zoukankan      html  css  js  c++  java
  • 算法总结——Bellman_ford

    Bellman_ford:

    复杂度:O(VE)  边数

    用途:一条路,钱币的互换,寻找最小正权环,即一圈后能回到自己并且比自己大或者小,如果是大,d数组就开0,否则开inf

    适用条件:从源点到它的所有节点,适用于稀疏图(顶点多,边数少)

    原理:利用该顶点判断操作之后与操作之前的比较

    步骤:1.开一个d数组,以d[s]记录初始值   2.n-1次松弛 3.判断每一个条件下是否盈利 4.如果每一个结点都盈利说明成功,否则说明存在负权环 

    模板:(main函数可忽略~只是为了方便了解各个参数如何得到) 

    n-1次原因:

    a->b, b->c, c->d这三条路径

    假设每一步都是最短路

    显然a->d是图中最短路径,最坏的情况是遍历的边先是c->d这条边,发现此时并不知道b->c是可以被用的,然后b->c, a->b

    这样一次循环结束,发现并没有得到最短路,然后现在已经得到d点是从c点过来最优,c点是从b点过来最优,b点是从a点过来最优

    那么假设又是最坏情况,仍旧是c->d, b->c, a->b, 此时结束后可以得到d点是从b点过来最优,c点是从a点过来最优

    第二次循环结束,第三次循环开始,就知道了d是从a过来最优,显然三次循环

    如果是最优的情况,即a->b, b->c, c->d

    第一次循环中就知道b是从a过来最优, c是从a过来最优, d是从a过来最优

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    struct edge{
        int u;
        int v;
        int rate;
    }a[300];
    int s;
    int d[300];
    int n,m;
    bool bellman_ford(int s)
    {
        for(int i = 1; i <= n ;i++)
            d[i] = 0;
        d[s] = 1;//第s种为单位1
        for(int i = 1; i <= n - 1 ; i++){//松弛n-1次,单纯循环
              int   flag = 1;
           for(int j = 1; j <= m ; j++){//一共就这么多交易规则
                if(d[a[j].v] < d[a[j].u]*a[j].rate){//如果盈利那么更新
                        flag = 0;
                  d[a[j].v] = d[a[j].u]*a[j].rate;
                }
           }
           if(flag) return true;//如果对于每一个交易规则,a[d[j].v]一直等于d[a[j].u]*d[j].rate,说明没有负环的存在,如果仅仅存在一个在接下来的交易中会把负环的接口补上
        }
        return false;//如果仍旧这样,说明存在了负环补不上,使得d[a[j].v]又减小了。
    }
    int main()
    {
        char temp[300][300];
        char  temp1[300],temp2[300];
        scanf("%d",&n);//一共n种货币
        for(int i = 1; i <= n ; i++)
            scanf("%s",temp[i]);
            scanf("%d",&m);//一共m种交易情况
        for(int i = 1; i <= m ; i++){
            scanf("%s%s%d",&temp1[i],&temp2[i],&a[i].rate);
           for(int j = 1; j <= n; j++){
               if(strcmp(temp[j],temp1) == 0)
                a[i].u = j;
               if(strcmp(temp[j],temp2) == 0)
                a[i].v = j;
            }
         }
         int flag1 = 0;
         for(int i = 1; i <= n ; i++)//任意一种钱出发
         if(bellman_ford(i)==0){
                flag1 = 1;
              printf("NO
    ");
         }
        if(!flag1)
            printf("YES
    ");
       return 0;
    }
  • 相关阅读:
    围棋角部大眼的气
    openwrt 增加自定义包
    OpenWrt – 编译前的./scripts/feeds脚本用法
    memset 赋初值为无穷大和无穷小
    android 自动点击学习课程
    最多硬币问题
    最少硬币问题
    9.2 嵌套矩形问题
    ajax请求到一个controller在跳转到下载的controller上也不能下载,百度了一下总结下原因:发现原来jQuery的ajax回调已经把response的数据傻瓜式的以字符串的方式解析.
    MySQL 数据库的远程访问权限
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4351777.html
Copyright © 2011-2022 走看看