就是有N種硬幣,M個兌換所,每個兌換所可以把A兌換成B或者把B換成A
A B Rab Cab Rba Cba可以表示一個兌換所,如果是x個A,則可以兌換成(x-Cab)*Rab個A,如果是x個B,則可以兌換成(x-Cba)*Rba個A,
然後某人現在有V個S種貨幣,問他能否在經過某些兌換後,最後能得到比V多的S種貨幣
這個題其實是一個判斷迴路的問題,類似於判斷負權迴路,這個題判斷的是正權迴路,就是每次都走最長的路(兌換儘可能多的錢)
用bellman-ford或者SPFA都行,我用的SPFA
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define eps 1e-7
#define maxn 103
#define maxm 10003
struct Edge
{
int next, to;
double R, C;
Edge() :next(0), to(0), R(0), C(0) { }
}edge[maxm];
int head[maxn], cnt = 0;
int N, M;
bool inq[maxn];
int cntq[maxn];
double dist[maxn];
void add(int u, int v, double R, double C)
{
edge[cnt].to = v;
edge[cnt].R = R; edge[cnt].C = C;
edge[cnt].next = head[u];
head[u] = cnt++;
}
bool SPFA(int S, double V)
{
memset(inq, false, sizeof(inq));
memset(cntq, 0, sizeof(int)*maxn);
memset(dist, 0, sizeof(double)*maxn);
queue<int> Q;
dist[S] = V;
inq[S] = true;
Q.push(S);
double val;
while (!Q.empty())
{
int u = Q.front(); Q.pop();
int v;
inq[u] = false;
for (int i = head[u]; i != -1; i = edge[i].next)
{
val = (dist[u] - edge[i].C)*edge[i].R;
if (val > dist[edge[i].to] && abs(val - dist[edge[i].to])>eps)
{
v = edge[i].to;
dist[v] = val;
if (!inq[v])
{
Q.push(v);
inq[v] = true;
if (++cntq[v] > N)
return false;
}
}
}
}
return true;
}
int main()
{
//freopen("input.txt", "r", stdin);
memset(head, -1, sizeof(int)*maxn);
cnt = 0;
int S; double V;
scanf("%d%d%d%lf", &N, &M, &S, &V);
int A, B;
double Rab, Rba, Cab, Cba;
for (int i = 0; i < M; ++i)
{
scanf("%d%d%lf%lf%lf%lf", &A, &B, &Rab, &Cab, &Rba, &Cba);
add(A, B, Rab, Cab); add(B, A, Rba, Cba);
}
bool flag = SPFA(S, V);
if (flag)
printf("NO\n");
else
printf("YES\n");
//system("pause");
//while (1);
return 0;
}