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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章