POJ1860—Bellman-Ford算法

这题和POJ2240是两道很经典的题目,这两道题目是求最大路径。本题是反向利用Bellman-Ford算法,求能无限松弛的最大路径,因此松弛操作的次数也不一定是n-1次(n是货币种类数),只要某一次松弛操作时,sum[s]的值能比输入的钱的数量大就可以,松弛操作的次数可能大于n-1次,也可能小于n-1次,在用Bellman-Ford算法求最短路径时,每次松弛可以设置一个标志,初值为false,如果有边可以更新,则置为true,当在某次松弛操作没法更新时,说明已经找到了最短路径长度,如果再更新,便会使得求得的距离比最短路径长度更大,此时flag值为false,直接退出,求出了最短路径。类似的,在本题中,每次松弛操作时都设置一个标志flag,初值均为false,每次松弛操作时,如果存在某条边使得货币总数增加,则置flag值为true,否则置为false,当为false时,直接退出,没有满足要求的最大路径。
 
#include <iostream>
#include <cstdio>
#include <cstring>
#define eps 1e-8
using namespace std;
const int maxn=102;
int n,m,s;
double money,sum[maxn];    //sum[i]为当前的钱在第i种货币下的价值

struct Edge
{
    int u;
    int v;
    double r;      //汇率
    double c;      //手续费
}edge[2*maxn];

bool Bellman_Ford(int num)
{
    int i;
    bool flag;
    sum[s]=money;
    while(sum[s]<money+eps)
    {
        flag=false;
        for(i=0;i<num;i++)
        if(sum[edge[i].v]<(sum[edge[i].u]-edge[i].c)*edge[i].r)
        {
            sum[edge[i].v]=(sum[edge[i].u]-edge[i].c)*edge[i].r;
            flag=true;
        }
        if(!flag)    //没有正权值的环使得资金增加,直接返回
        return false;
    }
    return true;
}

int main()
{
    int i,u,v,num;
    double ru,cu,rv,cv;
    bool flag;
    scanf("%d%d%d%lf",&n,&m,&s,&money);
    num=0;
    for(i=0;i<m;i++)
    {
        scanf("%d%d%lf%lf%lf%lf",&u,&v,&ru,&cu,&rv,&cv);
        edge[num].u=u;
        edge[num].v=v;
        edge[num].r=ru;
        edge[num++].c=cu;
        edge[num].u=v;
        edge[num].v=u;
        edge[num].r=rv;
        edge[num++].c=cv;
    }
    flag=false;
    memset(sum,0,sizeof(sum));
    flag=Bellman_Ford(num);
    if(flag)
    printf("YES\n");
    else
    printf("NO\n");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值