题目大意
你有好几种货币,是否能够通过不断地换似的s币的钱变多。(若A,B两种货币的汇率为 x,手续费为 y,w 单位的 A 货币,能换成 (w-y)*x个单位的 B 货币 )。
第一行输入四个整数,分别表示N货币总数,M兑换点的数目,S nick手上钱的类型,V nick手上钱的数目。
接下来M行每行6个整数,前两个表示A和B两种货币,接下来两个表示A换成B的汇率和手续费,最后两个表示B换成A的汇率和手续费。
题解
明显是判环的题目,我写的是spfa判环。
spfa判环和普通的spfa没啥区别,只是要记录每个点入队列的次数,如果大于等于 n 次就说明走进环里了(如果没有环,除去 i 点本身还有 n-1 个点,即使这 n-1 每个点都可以走到 i 一次,那么最多也只走到 n-1 次。而有环的情况下(理论上)会遍历到无数次)。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=105,maxm=105;
bool vis[maxn];
int n,m,s,h[maxn];
double v,f[maxn],q[maxn],c[maxn][maxn],p[maxn][maxn];
bool spfa(int x,double y)
{
q[1]=x;int til=1,hea=0;
memset(f,230,sizeof f);
f[x]=y;
memset(h,0,sizeof h);
memset(vis,0,sizeof vis);
while (hea!=til)
{
vis[x=q[(++hea)%=maxn]]=0;
for (int i=1;i<=n;i++)
if (c[x][i]>0&&(f[x]-p[x][i])*c[x][i]>f[i])
{
f[i]=(f[x]-p[x][i])*c[x][i];
if (vis[i]) continue;h[i]++;
if (h[i]>n) return 1;
vis[i]=1;q[(++til)%=maxn]=i;
}
}
return 0;
}
int main()
{
while (~scanf("%d%d%d%lf",&n,&m,&s,&v))
{
memset(c,230,sizeof c);
for (int i=1;i<=m;i++)
{
int x,y;scanf("%d%d",&x,&y);
scanf("%lf%lf%lf%lf",&c[x][y],&p[x][y],&c[y][x],&p[y][x]);
}
if (spfa(s,v)) printf("YES\n");else printf("NO\n");
}
return 0;
}