poj-2240

//600K	219MS	G++
#include <cstdio>
#include <string>
#include <map>
// #include <pair>
#include <cstring>
#include <cstdio>

using namespace std;

#define CURRENCY_MAX  33
#define EXCHANGE_MAX 1000

struct Exchange{
	int u;
	int v;
	double rate;
};

#define MINUS_INF -999999

typedef struct Exchange Exchange;

double currency_rate[CURRENCY_MAX][CURRENCY_MAX];
Exchange exchanges[EXCHANGE_MAX];

int currencyNum;
int exchangeNum;
double dis[CURRENCY_MAX];

map<string, int> currenyMap;

char BF() {
	for (int i = 1; i <= CURRENCY_MAX; i++) {
		dis[i] = MINUS_INF;
	}
	dis[1] = 1; // begin from curreny 1 and qunity is 1;
	for (int i = 2; i <= CURRENCY_MAX; i++) {
		for (int j = 0; j < exchangeNum; j++) {
			int u = exchanges[j].u;
			int v = exchanges[j].v;
			double rate = exchanges[j].rate;
			double original = dis[v];
			double relax;
			if (dis[u] == MINUS_INF) {
				relax = MINUS_INF; // MINS_INF * any is still MINUS_INF
			} else {
				relax = dis[u]*rate;
			}
			dis[v] = original > relax ? original : relax;
		}
	}

	for (int j = 0; j < exchangeNum; j++) {
		int u = exchanges[j].u;
		int v = exchanges[j].v;
		double rate = exchanges[j].rate;
		double original = dis[v];
		double relax;
		if (dis[u] == MINUS_INF) {
			relax = MINUS_INF; // MINS_INF * any is still MINUS_INF
		} else {
			relax = dis[u]*rate;
		}
		if (relax > original) {
			return 0;
		}
	}
	return 1;
}

void solve(int caseId) {
	// int edgeNum = 0;
	// for (int i = 1; i <= currencyNum; i++) {
	// 	for (int j = 1; j <= currencyNum; j++) {
	// 		if (currency_rate[i][j].rate > 0) { // can exchange
	// 			exchanges[edgeNum].u = i;
	// 			exchanges[edgeNum].v = j;
	// 			exchanges[edgeNum++].rate = currency_rate[i][j].rate;
	// 		}
	// 	}
	// }
	if (BF()) {
		printf("Case %d: No\n", caseId);
	} else {
		printf("Case %d: Yes\n", caseId);
	}
}

int main() {
	int caseId = 1;
	while(1) {
		scanf("%d", ¤cyNum);
		if (currencyNum == 0) {
			return 0;
		}
		currenyMap.clear();
		memset(currency_rate, 0, sizeof(currency_rate));
		memset(exchanges, 0, sizeof(exchanges));

		for (int i = 1; i <= currencyNum; i++) {
			char currencyName[100];
			scanf("%s", currencyName);
			currenyMap.insert(pair<string, int>(currencyName, i));
		}		
		scanf("%d", &exchangeNum);
		for (int i = 0; i < exchangeNum; i++) {
			char u[100];
			char v[100];
			double rate;
			scanf("%s %lf %s", u, &rate, v);
			int from = currenyMap.at(u);
			int to = currenyMap.at(v);
			currency_rate[from][to] = rate;
			exchanges[i].u = from;
			exchanges[i].v = to;
			exchanges[i].rate = rate;
		}
		solve(caseId++);
	}
}

600K    219MS    G++

和1860一个套路,只不过多了一字符串转整数index的步骤罢了,

一般来说,加这个转换可能是为了考察 hashMap或者tire树之类的应用,

不过因为前一轮已经把这两个考点干了一遍了,不想再搞,就直接STL的hashMap搞起了,

反正重点也不是这里,

转换成整数index以后就好办了,直接BF算法检测正权环就可以了,

注意题目和1860的不同在于,1860是指定了源点的(不过因为题目本身又保证了点之间都是可达的,所以也不算什么约束条件),

本题没有指定源点,只在乎有没有正环,如同上一道题说的那样,BF检测环的前提是开始的源点是可以到达环的,

所以最严谨的做法是每个点来一遍BF检测环,或者将图分成几个子图(子图中每个点都互可达其他点)然后子图中随便找一个点做源点BF。

不过貌似这种题都不care这种情况,因此不搞了(数据也弱),随便找一个源点做一次正环判断。

一个注意的是,随便选择的源点的dis[]数组的取值,

在1860中,每个点的dis值代表从源点currencyS开始到此点能兑换的最多S,而题目最开始给了一个初始的S的面值,因此可以将源点的dis置为该面值

本题中没有给出,也不影响,因为比较结果是一个相对比较,初始值是多少没关系的,因此直接把起始点的dis设为1就OK。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值