这两天跑步晚上睡得不够早,导致体能有点不足,今天好虚的感觉,有点想休息一天,但是一想到我这么水,还是来写题解吧。今天写的是今天和昨天两天做的不是特别水的水题。
题意:
有N种现金,有M个换钱的地方,一个地方可以进行两种货币之间的双向兑换。把a币兑换成b币,需要付手续费c,兑换率为r,则用x单位的a币可以得到(a-c)*r的b币。求是否存在一种方法,通过兑换的方式,增加钱的数量。
Input
The first line of the input contains four numbers: N - the number of currencies, M - the number of exchange points, S - the number of currency Nick has and V - the quantity of currency units he has. The following M lines contain 6 numbers each - the description of the corresponding exchange point - in specified above order. Numbers are separated by one or more spaces. 1<=S<=N<=100, 1<=M<=100, V is real number, 0<=V<=10
3.
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10 -2<=rate<=10 2, 0<=commission<=10 2.
Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations will be less than 10 4.
For each point exchange rates and commissions are real, given with at most two digits after the decimal point, 10 -2<=rate<=10 2, 0<=commission<=10 2.
Let us call some sequence of the exchange operations simple if no exchange point is used more than once in this sequence. You may assume that ratio of the numeric values of the sums at the end and at the beginning of any simple sequence of the exchange operations will be less than 10 4.
Output
If Nick can increase his wealth, output YES, in other case output NO to the output file.
这题乍一看是广搜的节奏,但是还是用bellman的过程写了,最后还是WA了,后来想明白了为什么,也知道了为什么不能用广搜而要用最短路算法。
这个题不是为了求最短路而用最短路算法,而是为了判断环。由于这个图是双向的,所以能到一个点肯定可以回去,如果在某一块存在正环,那么价值就可以无限增大,总有一天再回到起点可以大于原来起点的值。
所以只要用bellman或者SPFA判出正环,就返回true,如果不存在环,则肯定不可能增大,返回false。最短路或者说最长路的数值没有意义。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
#define mxn 110
#define mxm 250
int first[mxn],nxt[mxm],vv[mxm],cnt;
double rr[mxm],cc[mxm];
bool dcmp(double x,double y){
return fabs(x-y)<0.00000001;
}
void add(int u,int v,double r,double c){
nxt[cnt]=first[u];
first[u]=cnt;
vv[cnt]=v;
rr[cnt]=r;
cc[cnt++]=c;
}
void init(){
memset(first,-1,sizeof(first));
cnt=0;
}
int n,m,s;
double st,money[mxn];
int rec[mxn];
double ex(int now,int k){
if(money[now]<cc[k]&&!dcmp(money[now],cc[k]))
return money[vv[k]];
return max((money[now]-cc[k])*rr[k],money[vv[k]]);
}
bool bellman(){
memset(rec,0,sizeof(rec));
memset(money,0,sizeof(money));
money[s]=st;
for(int i=0;i<2*n;++i){
bool flag=false;
for(int j=1;j<=n;++j)
for(int k=first[j];k!=-1;k=nxt[k]){
double tem=ex(j,k);
if(tem>money[vv[k]]){
++rec[vv[k]];
money[vv[k]]=tem;
flag=true;
}
}
if(!flag) break;
}
for(int i=1;i<=n;++i)
if(rec[i]>=n) return true;
if(money[s]>st&&!dcmp(money[s],st))
return true;
return false;
}
int main(){
while(scanf("%d%d%d%lf",&n,&m,&s,&st)!=EOF){
init();
for(int i=0;i<m;++i){
int u,v;
double r1,c1,r2,c2;
scanf("%d%d%lf%lf%lf%lf",&u,&v,&r1,&c1,&r2,&c2);
add(u,v,r1,c1);
add(v,u,r2,c2);
}
bool ans=bellman();
if(ans) puts("YES");
else puts("NO");
}
return 0;
}