POJ1860---Currency Exchange (最短路:验证是否存在正环)

来源:互联网 发布:mysql数据库书籍 编辑:程序博客网 时间:2024/06/06 03:30

【题目来源】:https://vjudge.net/problem/POJ-1860
【题意】
有多种汇币,给出从A币到B币的汇率和手续费。计算公式:
money(B)=(money(A)-手续费)*汇率。
给出本金钱数和钱币的类型,问经过转换汇币类型是否能够增加钱的数目。
【思路】
这道题也就是要求验证是否存在正环,若是存在正环,那么钱数一定会增加。关键是怎么验证是否存在正环。
验证是否存在负环很容易,bellman个spfa都可以:推荐博客:验证负环,然后,验证负换可以简单地把bellman算法反过来用就行。本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,初始化d(S)=V 而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径。
【代码】

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;int n,m,s,l;double money;struct p{    int u,v;    double point,pound;} edge[200+10];double d[100+10];bool bellman(){    for(int i=1; i<=n; i++)        d[i]=0;    d[s]=money;    for(int i=1; i<=n-1; i++)    {        bool flag=1;        for(int j=0; j<l; j++)        {            double t= (d[edge[j].u]-edge[j].pound)*edge[j].point;            if(d[edge[j].v]<t)            {                d[edge[j].v]=t;                flag=0;            }        }        if(flag) return 0;    }    for(int i=0; i<l; i++)    {        double t= (d[edge[i].u]-edge[i].pound)*edge[i].point;        if(d[edge[i].v]<t)            return 1;    }    return 0;}int main(){    l=0;    scanf("%d%d%d%lf",&n,&m,&s,&money);    for(int i=1; i<=m; i++)//输入m条边。。不对,是2*m,,,    {        int u,v;        double po1,pr1,po2,pr2;        scanf("%d%d%lf%lf%lf%lf",&u,&v,&po1,&pr1,&po2,&pr2);        edge[l].u=u;        edge[l].v=v;        edge[l].point=po1;        edge[l++].pound=pr1;        edge[l].u=v;        edge[l].v=u;        edge[l].point=po2;        edge[l++].pound=pr2;    }    if(bellman())        printf("YES\n");    else        printf("NO\n");}
阅读全文
0 0
原创粉丝点击