POJ1860 Currency Exchange(最短路径)

来源:互联网 发布:java pop3 编辑:程序博客网 时间:2024/06/04 19:28

题意::

有n种货币,m种兑换方式,每次兑换是这样计算的:如果一开始有V单位b货币,Rab是从a换到b的汇率,Cab是交换需要的手续费,最后能换到(V-Cab)*Rab单位b货币。一开始的货币种类是s,要求最后换回s,问能否进行一系列兑换,使最后换回s时钱增加。

要点:

如果能够经过一个回路返回起点使钱增加,那么可以经过无数次回路,使钱无限增多。所以就转化为bellman算法求是否有负权回路问题,只不过这题稍微变形了一下,恰恰与bellman算法的松弛条件相反,求的是能无限松弛的最大正权路径,因此初始化d(S)=V 而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径。这题我WA了很多次,明明思路对的,最后发现我代码里用了两个v,一个表示初始金钱,一个表示边的终点。下次变量多的题尽量用长的变量名称。


15377480Seasonal1860Accepted200K32MSC++1033B2016-04-11 06:25:03

#include<stdio.h>#include<string.h>#include<stdlib.h>struct edge{int u, v;double rate,cost;}e[3000];int n, m, s,num;double value;double dis[1000];bool bellman(){memset(dis, 0, sizeof(dis));dis[s] = value;bool flag;for (int i = 1; i <= n-1; i++){flag = false;for (int j = 0; j < num; j++)if (dis[e[j].v]<(dis[e[j].u] - e[j].cost)*e[j].rate)//进行放大松弛{dis[e[j].v] = (dis[e[j].u] - e[j].cost)*e[j].rate;flag = true;}if (!flag)break;}for (int j = 0; j < num; j++)//判断还能否松弛,如果可以说明有无穷大回路if (dis[e[j].v]<(dis[e[j].u] - e[j].cost)*e[j].rate)return true;return false;}int main(){int u, v;double r1, r2, c1, c2;while (scanf("%d%d%d%lf", &n, &m, &s, &value)!=EOF){num = 0;for (int i = 0; i<m; i++){scanf("%d%d%lf%lf%lf%lf", &u, &v, &r1, &c1, &r2, &c2);e[num].u = u; e[num].v = v;e[num].rate = r1;e[num++].cost = c1;e[num].u = v; e[num].v = u;e[num].rate = r2; e[num++].cost = c2;}if (bellman())printf("YES\n");elseprintf("NO\n");}return 0;}


0 0
原创粉丝点击