POJ 1860 Currency Exchange 【spfa判断正环】

POJ 1860 Currency Exchange 【spfa判断正环】

原题链接:传送门

题目大意:
给出几种货币以及它们正向反向兑换的汇率和手续费,
求给定一种货币以及金额,问能否经过若干次货币兑换后回到原给定的货币种类,
若能实现金额数增加则输入YES,否则输出NO

具体思路:
最短路变形,spfa求解,若换到某种货币金额数大于该种货币原有金额则更新,若发现某条边更新了超过n次,说明存在正环,能赚到钱(即走一次环换成该种货币赚一点点,当走多次环,积少成多,总会出现赚的钱大于换回原有货币所需的佣金)
因此可根据图中是否存在正环判断能否赚到钱

具体代码:

#include<iostream>
#include<cstdio>
#include<stdlib.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 105;
struct Node {
	int x, y;
	double r, c;
	Node(int x, int y, double r, double c)
	{
		this->x = x, this->y = y;
		this->r = r, this->c = c;
	}
};
vector<Node> maps[N];	//用stl来存图
int visit[N];	//记录是否在队列中
int index[N];	//记录入队次数
double d[N];	//d[i]表示一开始的钱换成i种货币时,i种货币能环到的数额
int n, m, kind;
double money;
int flag = 0;

void spfa()
{
	for (int i = 1; i <= n; i++)
		visit[i] = 0, index[i] = 0, d[i] = 0;
	d[kind] = money;	//初始化原有货币种类的数额
	visit[kind] = 1;
	index[kind] = 1;
	queue<int> q;
	q.push(kind);
	while (q.size())
	{
		int t = q.front();
		q.pop();
		visit[t] = 0;
		for (vector<Node>::iterator it = maps[t].begin(); it != maps[t].end(); it++)
		{
			double get = (d[t] - it->c)*it->r;

			if (d[it->y] < get) {	//若换成该货币,该种货币的金额数有增加
				d[it->y] = get;
				if(visit[it->y])continue;
				visit[it->y] = 1;
				q.push(it->y);
				index[it->y]++;
				if (index[it->y] > n) {	//有正环
					flag = 1;
					return;
				}
			}
			
		}
	}
}

int main()
{
	cin >> n >> m >> kind >> money;
	for (int i = 1; i <= m; i++)
	{
		int x, y;
		double r1, c1, r2, c2;
		cin >> x >> y >> r1 >> c1 >> r2 >> c2;
		maps[x].push_back(Node(x, y, r1, c1));
		maps[y].push_back(Node(y, x, r2, c2));
	}
	spfa();
	if(flag)printf("YES\n");
	else printf("NO\n");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章