算法总结——Bellman_ford

Bellman_ford:

复杂度:O(VE)  边数

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

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

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

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

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

#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\n");

     }

    if(!flag1)

        printf("YES\n");

   return 0;

}

 

你可能感兴趣的:(for)