题意:
我们城市里面有几个货币交换点。 我们假设每一个交换点有特定的两种货币并且提供交换操作,只限于这两个货币。允许有几个不同的货币交换点交换相同的一对货币。每一个货币交换点有他自己的汇率,A对B的交换率是定量的B去交换1个A。每一个交换点需要一些佣金,这个佣金是交换货币的代价。佣金用源货币去交换。例如,你要交换100美金换成卢布在交换点。交换率是29.75,佣金0.39,你可以得到(100 – 0.39) * 29.75 = 2963.3975卢布。你确切的知道有N种不同的货币你可以在你们的城市进行交换。假设为1 – N。然后每一个交换点被描述为6个数字,整数A和B–可以交换的钱,和Rab,Cab,Rba,Cba–交换律和佣金当交换A->B和B->A。Nick有一些货币S随意交换,在多次操作之后提升他的钱。当然,他想让他的钱最后还是货币S。帮助他解决这个问题。Nick在他操作的时候保证钱的总和是非负数的。
想法:看完题意,边的个数200,只要图中有正环就可以无限扩大自己的钱数,然后不过后面是削弱了多少。因为是双向边所以一定可以重回到原先的货币种类,所以只要有正环就可以回到起点涨价了。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const double inf = 1005.00;
const int max_node = 105;
const int max_edge = 105;
int N, M, S;
int edge_cnt;
double V;
struct c_point{
int u, v;
double change_rate;
double commssions;
}edge[max_edge * 2];
void _init()
{
edge_cnt = 0;
}
bool Bellman_ford()
{
double dis[max_node];
for(int i = 1; i <= N; ++i){
dis[i] = -1;
}
dis[S] = V;
for(int i = 1; i <= N - 1; ++i){
for(int j = 1; j <= 2 * M; ++j){
int u = edge[j].u;
int v = edge[j].v;
if(dis[u] != -1 && dis[v] < (dis[u] - edge[j].commssions) * edge[j].change_rate){
dis[v] = (dis[u] - edge[j].commssions) * edge[j].change_rate;
}
}
}
for(int j = 1; j <= 2 * M; ++j){
int u = edge[j].u;
int v = edge[j].v;
if(dis[u] != -1 && dis[v] < (dis[u] - edge[j].commssions) * edge[j].change_rate){
//cout<<(dis[u] - edge[j].commssions) * edge[j].change_rate<<endl;
return true;
}
}
return false;
}
int main()
{
while(cin>>N>>M>>S>>V){
_init();
for(int i = 1; i <= M; ++i){
int A, B;
double Rab, Cab, Rba, Cba;
cin>>A>>B>>Rab>>Cab>>Rba>>Cba;
edge[++edge_cnt].u = A;
edge[edge_cnt].v = B;
edge[edge_cnt].change_rate = Rab;
edge[edge_cnt].commssions = Cab;
edge[++edge_cnt].u = B;
edge[edge_cnt].v = A;
edge[edge_cnt].change_rate = Rba;
edge[edge_cnt].commssions = Cba;
}
if(Bellman_ford()) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}