题意:
我们城市里面有几个货币交换点。 我们假设每一个交换点有特定的两种货币并且提供交换操作,只限于这两个货币。允许有几个不同的货币交换点交换相同的一对货币。每一个货币交换点有他自己的汇率,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; }