传送门:点击打开链接
题目大意:一个城市有n种货币,m个货币交换点,你有v的钱,每个交换点只能交换两种货币,(A换B或者B换A),每一次交换都有独特的汇率和手续费,问你存不存在一种换法使原来的钱更多。
思路:一开始以为一个地方只能用一次,感觉好像有点难,后来发现自己读错题了,其实只要判断给你的这幅图存不存在正环就可以了,用dis【】表示某种货币的数量,然后bellman判断正环就可以了。(题目里强调结尾一定要原来的货币,但其实这是废话,因为是以原来的货币为起点的,所以你换出去了一定换的回来),正环指的是跑一圈w变大的环。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<math.h> #include<cmath> #include<time.h> #include<map> #include<set> #include<vector> #include<queue> #include<algorithm> #include<numeric> using namespace std; int n,m,s,num; const int maxn=110; double V,dis[maxn]; struct edge{ int u,v; double cost,w; }e[220]; void addv(int a,int b,double ra,double ca){ e[num].u=a; e[num].v=b; e[num].cost=ca; e[num++].w=ra; } bool bellman(){ dis[s]=V; for(int i=1;i<n;i++){//松弛n-1次 bool flag=false; for(int j=0;j<num;j++){ int u=e[j].u; int v=e[j].v; if(dis[v]<(dis[u]-e[j].cost)*e[j].w){ dis[v]=(dis[u]-e[j].cost)*e[j].w; flag=true; } } if(!flag)return false;// 如果n-1次都无法松弛 那肯定不存在正环 } for(int i=0;i<num;i++){ if(dis[e[i].v]<(dis[e[i].u]-e[i].cost)*e[i].w)//第n次若能松弛 说明存在正环 return true; } return false; } int main(){ while(scanf("%d%d%d%lf",&n,&m,&s,&V)!=EOF){ num=0; sizeof(dis,0,sizeof(dis)); while(m--){ int a,b; double ra,ca,rb,cb; scanf("%d%d%lf%lf%lf%lf",&a,&b,&ra,&ca,&rb,&cb); addv(a,b,ra,ca); addv(b,a,rb,cb); } if(bellman())printf("YES\n"); else printf("NO\n"); } }