POJ 1860 Currency Exchange SPFA判回路

19 篇文章 0 订阅

就是有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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值