本题要求从源点出发的货币经过一些列交换是否能增值,也即是求是否存在正环。
参考本博POJ 3259中求负环详细分析,同理若存在正环则我们可以对其中的点无限松弛,即从源点出发的货币若能在|V|-1次对所有边松弛以后还能增值,则从源点出发存在正环。又因为路径都是双向的,则从正环也必定能返回源点,所以原货币必定能增值。
注意初始化时个货币初值为0,因为要能从源点出发增值,不能取负值,题目也规定每次交易货币量必须为非负值。
#include<iostream>
#include<cstdio>
using namespace std;
short currNum;
short exchNum;
short currHave;
double currQuan;
double* val; //从最初货币开始兑换能得到的对应键值货币的最大量
double* rate;
double* commi;
struct edge
{
short px,py;
}*edges;
bool IsWealCrea()
{
int i,j;
int px,py;
val = new double[currNum+1];
for(i = 1;i <= currNum;i++)
val[i] = 0;
val[currHave] = currQuan;
for(i = 0;i < currNum-1;i++)
{
for(j = 0;j < 2*exchNum;j++)
{
px = edges[j].px;
py = edges[j].py;
if(val[py] < (val[px]-commi[j])*rate[j])
val[py] = (val[px]-commi[j])*rate[j];
}
}
for(j = 0;j < 2*exchNum;j++)
{
px = edges[j].px;
py = edges[j].py;
if(val[py] < (val[px]-commi[j])*rate[j])
return true;
}
return false;
}
int main()
{
int i = 0;
short px,py;
while(cin>>currNum>>exchNum>>currHave>>currQuan)
{
edges = new edge[2*exchNum];
rate = new double[2*exchNum];
commi = new double[2*exchNum];
for(i = 0;i < exchNum;i++)
{
cin>>px>>py;
cin>>rate[i*2]>>commi[i*2]>>rate[i*2+1]>>commi[i*2+1];
edges[i*2].px = edges[i*2+1].py = px;
edges[i*2].py = edges[i*2+1].px = py;
}
if(IsWealCrea())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}