题目大意:给出n种货币,m种兑换方式,初始时你拥有的是第s种货币,价值为s。接下来m行每行前两个数代表两种货币,之后四个数分别代表,第一种货币到第二种货币的汇率和所要交的佣金,第二种到第一种货币的汇率和所要交的佣金。问能否在拥有初始货币数量的情况下,多次兑换后使得这种货币的数量增加。
思路:判环,当有一个点入队次数大于n时说明有一个环能让数值一直变大。(SPFA判环技巧)
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#define inf 0x3fffffff
using namespace std;
const double eps=0.00000001;
const int maxn=550;
int first[maxn],sign;
int n;
double dis[maxn];
int vis[maxn],s,inq[maxn];
double v;
struct node
{
int to,next;
double c,r;
}edge[maxn*maxn];
void creat()
{
for(int i=0;i<maxn;i++)
first[i]=0;
sign=1;
}
void add_edge(int u,int v,double r,double c)
{
edge[sign].to=v;
edge[sign].c=c;
edge[sign].r=r;
edge[sign].next=first[u];
first[u]=sign++;
}
int SPFA(int top,double num)
{
inq[top]++;
if(inq[top]>n)return 1;
vis[top]=0;
for(int i=first[top];i;i=edge[i].next)
{
int to=edge[i].to;
double r=edge[i].r;
double c=edge[i].c;
if((num-c)*r>dis[to])
{
dis[to]=(num-c)*r;
if(!vis[to])
{
vis[to]=1;
if(SPFA(to,dis[to]))
return 1;
}
}
}
return 0;
}
int main()
{
int m;
scanf("%d %d %d %lf",&n,&m,&s,&v);
creat();
int uu,vv;
double r1,c1,r2,c2;
for(int i=0;i<m;i++)
{
scanf("%d %d %lf %lf %lf %lf",&uu,&vv,&r1,&c1,&r2,&c2);
add_edge(uu,vv,r1,c1);
add_edge(vv,uu,r2,c2);
}
dis[s]=v;
memset(vis,0,sizeof(vis));
if(SPFA(s,v))
puts("YES");
else
puts("NO");
return 0;
}