//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。