[POJ 1860] Currency Exchange 最短路判正环(SPFA版)

来源:互联网 发布:网络社交的利弊二辩 编辑:程序博客网 时间:2024/06/05 13:33

题目传送门:【POJ 1860】

题目大意:你需要通过兑换货币来赚钱,N 座城市有 M 个货币兑换点(可看作有 N 个点和有 M 条边的图),你每兑换一次货币需要支付一定佣金才能兑换。例如,你想把 100 美元换成俄罗斯卢布,如果那里的汇率是 29.75,而佣金是 0.39,你会得到(100 - 0.39)×29.75=2963.3975 卢布。求最后能否通过不断地兑换货币使得自己的财富源源不断地增长。当然,在兑换过程中,你拥有的钱不能为负值。

题目分析:
考察对于最短路的理解及灵活的变换(运用)。
本题的目的是要让主人公不断地通过兑换货币获利,如果在这个图上有正环,那么只要不停地沿着正环走,那么财富就会不断增长,此时就满足题意了。
因此,这道题在初始化时,应该与普通的最短路算法相反,初始化为非常小的值。此时判断正环即与原来的判断负环的方式相反。(当然,判断的思路是一样的。)

下面附上代码:

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int MX=10005;struct Edge{    int to,next;    double rate,com;};Edge edge[MX];int n,m,w,now = 0,head[MX];double ori;                                  //原有的货币数量void adde(int u,int v,double r,double c){    edge[++now].to = v;    edge[now].rate = r,edge[now].com = c;    edge[now].next = head[u];    head[u] = now;}bool spfa(int s){    queue<int> q;    int cnt[MX] = {0};    double dis[MX];                          //在这个点所有的钱的最大值    bool vis[MX];    memset(dis,0xef,sizeof(dis));    dis[s] = ori,vis[s] = true,q.push(s);    while (!q.empty()){        int u = q.front();        q.pop();        for (int i = head[u];i;i = edge[i].next){            int v = edge[i].to;            if ((dis[u] - edge[i].com) * edge[i].rate > dis[v]){                dis[v] = (dis[u] - edge[i].com) * edge[i].rate;    //判断的方式有改变。这里,如果兑换后的钱比原来的多,那么就更新;否则不变                cnt[v]++;                q.push(v);                vis[v] = true;                if (cnt[v] >= n) return true;//判断正环            }        }    }    return false;}int main(){    int a,b;    double p1,q1,p2,q2;            //p:汇率, q:佣金    cin>>n>>m>>w>>ori;    for (int i = 1;i <= m;i++){        cin>>a>>b>>p1>>q1>>p2>>q2;        adde(a,b,p1,q1);        adde(b,a,p2,q2);    }    if (spfa(w)) cout<<"YES"<<endl;    else cout<<"NO"<<endl;}
原创粉丝点击