题意分析
给出货币相互对换的汇率,求经过若干次对换之后,能否使得原来的货币变多。
将每种货币看做成一个点,将对换看做是边,使用BellmanFord判断是否含有正环即可。
因为正环的含义就是,可以多次走这个环,使得每次对换后相应的货币变多。
代码总览
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int nmax = 10000;
const double INF = 999999999.0;
double dis[nmax];
int head[nmax];
int tot = 0;
int n,m,s;
double v;
struct Edge{
int to,nxt;
double val,tip;
Edge(){}
Edge(int _u, int _v, double _val, double _tip ){
to = _v; nxt = head[_u]; val = _val; tip = _tip;
}
};
Edge edge[nmax<<1];
void init(){
tot = 0;
memset(head,-1,sizeof head);
memset(edge,0,sizeof edge);
}
inline void add(int _u, int _v, double _val, double _tip){
edge[tot] = Edge(_u,_v,_val,_tip);
head[_u] = tot ++;
}
bool Bellman(int st){
for(int i = 1;i<=n;++i) dis[i] = 0.0;
dis[st] = v;
for(int k = 2;k<=n;++k){
for(int i = 1;i<=n;++i){
for(int j = head[i];j!=-1;j = edge[j].nxt){
int to = edge[j].to;
dis[to] = max(dis[to], (dis[i] - edge[j].tip) * edge[j].val);
}
}
if(dis[st] > v) return true; // 经过循环后货币变多
}
for(int i = 1;i<=n;++i){ // 最后判断正环
for(int j = head[i];j!=-1;j = edge[j].nxt){
int to = edge[j].to;
if(dis[to] < (dis[i] - edge[j].tip) * edge[j].val )
return true;
}
}
return false;
}
int main(){
while(scanf("%d %d %d %lf",&n,&m,&s,&v)!=EOF){
init();
int f,t; double r1,t1,r2,t2;
for(int i = 0;i<m;++i){
scanf("%d %d %lf %lf %lf %lf",&f,&t,&r1,&t1,&r2,&t2);
add(f,t,r1,t1); add(t,f,r2,t2);
}
bool isok = Bellman(s);
if(isok) printf("YES\n");
else printf("NO\n");
}
return 0;
}