poj 1860 Currency Exchange bellman
题目大意
有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加,因为货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路。
分析
就是要求有没有正环,用bellman求最长路,经过n次松弛后如果还可以松弛,那就有正环,输出YES。
注意
要把每种汇币当做点,把交换当做边,权值为一个函数:(现在有的钱-手续费)*汇率
代码
const maxe=10000; maxv=20000; type arr=record x,y:longint; w,t:real; end; var n,m,f:longint; s:real; a:array[1..maxv] of arr; d:array[1..maxe] of real; i,j,k:longint; procedure relax(u,v:longint;w,t:real); var i:real; begin i:=(d[u]-t)*w; if i>d[v] then d[v]:=i; end; function bellman:boolean; var i,j:integer; k:real; begin for i:=1 to n do for j:=1 to m do with a[j] do relax(x,y,w,t); for i:=1 to m do with a[i] do begin k:=(d[x]-t)*w; if k>d[y] then exit(true); end; exit(false) end; begin readln(n,m,f,s); fillchar(a,sizeof(a),0); fillchar(d,sizeof(d),0); for j:=1 to m do begin with a[j*2-1] do read(x,y,w,t); a[j*2].x:=a[j*2-1].y; a[j*2].y:=a[j*2-1].x; with a[j*2] do read(w,t); end; m:=m*2; d[f]:=s; if bellman then writeln('YES') else writeln('NO'); end.