题意:你现在有N种类型的货币,这N种类型的货币之间有M种汇率关系,然后输入M组关系,A,rate,B,表示每单位A货币可以换rate的B货币。问你有没有方法使自己的钱增多?
思路:判断是否正环。货币类型用MAP映射成数字,然后建图。把你有的货币都设置为1的本金。然后跑一边Floyd看有没有货币使得自己变多了。或者跑N遍BellmanFord看有没有哪 次出现了正环。松弛条件改为权值可以变大时,可以松弛。
坑点:注意要交C++,交G++可能会超时。
Floyd:
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<map>
using namespace std;
const int MAXN = 35;
int n, m;
double d[MAXN][MAXN];
void Floyd()
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
d[i][j] = max(d[i][j], d[i][k] * d[k][j]);
}
}
}
}
int main()
{
int CASE = 1;
while (~scanf("%d", &n) && n)
{
memset(d, 0, sizeof(d));
map<string, int> M;
for (int i = 0; i < n; i++)
{
string str; cin >> str;
M[str] = i;
d[i][i] = 1;
}
scanf("%d", &m);
while (m--)
{
string u, v;
double rate;
cin >> u >> rate >> v;
d[M[u]][M[v]] = rate;
}
Floyd();
bool flag = false;
for (int i = 0; i < n; i++)
{
if (d[i][i] > 1.0) { flag = true; break; }
}
printf("Case %d: ", CASE++);
if (flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
/*
3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar
3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar
0
*/
SPFA(队列优化BellmanFord):
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int MAXN = 505;
const int INF = 0x3f3f3f3f;
struct Edge
{
int from, to/*, dist*/; //起点,终点,距离
double rate;
//Edge(int u, int v, int w):from(u), to(v), dist(w) {}
Edge(int u, int v, double w):from(u), to(v), rate(w) {}
};
struct BellmanFord
{
int n, m; //结点数,边数(包括反向弧)
vector<Edge> edges; //边表。edges[e]和edges[e^1]互为反向弧
vector<int> G[MAXN]; //邻接表,G[i][j]表示结点i的第j条边在edges数组中的序号
bool vis[MAXN]; //是否在队列中
//int d[MAXN]; //Bellman-Ford
double d[MAXN];
int p[MAXN]; //上一条弧
int cnt[MAXN]; //进队次数
void init(int n)
{
this->n = n;
edges.clear();
for (int i = 0; i <= n; i++) G[i].clear();
}
//void add_edge(int from, int to, int dist)
void add_edge(int from, int to, double rate)
{
//edges.push_back(Edge(from, to, dist));
edges.push_back(Edge(from, to, rate));
m = edges.size();
G[from].push_back(m - 1);
}
bool bellman_ford(int s)
{
for (int i = 0; i <= n; i++) d[i] = -INF;
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
d[s] = 1; vis[s] = true;
queue<int> Q;
Q.push(s);
while (!Q.empty())
{
int u = Q.front(); Q.pop();
vis[u] = false;
for (int i = 0; i < G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
//if (d[u] < INF && d[e.to] > d[u] + e.dist)
if (d[u] > -INF && d[e.to] < d[u] * e.rate)
{
//d[e.to] = d[u] + e.dist;
d[e.to] = d[u] * e.rate;
p[e.to] = G[u][i];
if (!vis[e.to])
{
Q.push(e.to); vis[e.to] = true;
if (++cnt[e.to] > n) return false;//有负环
}
}
}
}
return true;//没有负环
}
};
BellmanFord solve;
int main()
{
int n, m, CASE = 1;
while (~scanf("%d", &n) && n)
{
solve.init(n);
map<string, int> M;
for (int i = 0; i < n; i++)
{
string str; cin >> str;
M[str] = i;
}
scanf("%d", &m);
while (m--)
{
string u, v;
double rate;
cin >> u >> rate >> v;
solve.add_edge(M[u], M[v], rate);
}
bool flag = false;
for (int i = 0; i < n; i++)
{
if (!solve.bellman_ford(i)) { flag = true; break; }
}
printf("Case %d: ", CASE++);
if (flag) printf("Yes\n");
else printf("No\n");
}
return 0;
}
/*
3
USDollar
BritishPound
FrenchFranc
3
USDollar 0.5 BritishPound
BritishPound 10.0 FrenchFranc
FrenchFranc 0.21 USDollar
3
USDollar
BritishPound
FrenchFranc
6
USDollar 0.5 BritishPound
USDollar 4.9 FrenchFranc
BritishPound 10.0 FrenchFranc
BritishPound 1.99 USDollar
FrenchFranc 0.09 BritishPound
FrenchFranc 0.19 USDollar
0
*/