import java.util.Scanner;
public class Main
{
private int n; //全部有多少种货币
private int m; //有多少兑换方法
private Currency[] currencies;
private double[] dis; //解出到了第i种货币时,对应的货币值
private class Currency
{
public int s1; //货币1
public int s2; //货币2
public double r; //汇率
public double c; //手续费
Currency( int s1,int s2,double r,double c )
{
this.s1 = s1;
this.s2 = s2;
this.r = r;
this.c = c;
}
}
public void Relax( Currency currency ) //主要是参考《算导》里面的松弛技术
{
if( this.dis[currency.s2] < (this.dis[currency.s1]-currency.c)*currency.r )
this.dis[currency.s2] = (this.dis[currency.s1]-currency.c)*currency.r;
}
public boolean isIncrease() //主要是参考《算导》里面的Bellman-Ford算法
{
for( int i=1;i<=n-1;i++ )
{
for( int j=0;j<2*m;j++ )
{
this.Relax( this.currencies[j] );
}
}
for( int i=0;i<2*m;i++ )
{
Currency currency = currencies[i];
if( this.dis[currency.s2] < (this.dis[currency.s1]-currency.c)*currency.r )
return true;
}
return false;
}
Main( int n,int m,int s,double v ) //初始化
{
this.n = n;
this.m = m;
this.currencies = new Currency[2*m];
this.dis = new double[n+1];
dis[s] = v;
}
public void setM( int i,int s1,int s2,double r12,double c12,double r21,double c21 ) //设置初始值
{
this.currencies[i] = new Currency( s1,s2,r12,c12 );
this.currencies[i+1] = new Currency( s2,s1,r21,c21 );
}
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int m = s.nextInt();
int S = s.nextInt();
double v = s.nextDouble();
int i=0;
Main main = new Main( n,m,S,v );
while( i<2*m )
{
int s1 = s.nextInt();
int s2 = s.nextInt();
double r12 = s.nextDouble();
double c12 = s.nextDouble();
double r21 = s.nextDouble();
double c21 = s.nextDouble();
main.setM( i,s1,s2,r12,c12,r21,c21 ); //设置所有的边
i+=2;
}
if( main.isIncrease() )
System.out.println( "YES" );
else
System.out.println( "NO" );
}
}
这道题目,可以这么理解:一种货币,就是图上的一个点。一种兑换方法,就是这两个点之间的一个环。当货币A的数量为V时,它到货币B的兑换方法为:(A-Cab)*Rab
上式中,Cab为A、B之间的手续费,Rab为兑换率。(A-Cab)*Rab得到的结果为A到B的权值。
题目要我们判断最终的财富是不是可以增加,也就是说,要找到最大的路径。其中,货币的兑换是可以无限次数的,换句话说,只要我们找到一个正的回路,在里面无限循环执行,那么财富肯定可以增加。现在,我们要判断的,就是是不是有这样的回路。这和《算法导论》里面的“负回路”可以说是如出一辙。
所以,我们可以参考Bellman-Ford算法(算法正确性的证明可以参照《算法导论》)
好了,下面是废话:
唉,还是不会抽丝剥茧那样进行归纳总结来解决问题。也是参考了《算法导论》和网上的代码http://blog.youkuaiyun.com/lyy289065406/article/details/6645778
在写完之后,还因为没弄好A,B之间的兑换关系,还卡了一会儿,才解决了问题。
看来,分析问题的能力和仔细程度还是有待提高啊。唉!!!!!!