SP9340 题解
前言
趣味的 Floyd。
思路
容易发现,套利就是一大堆兑换的数值的成绩。我们希望这个数值大于 \(1\)。
可以想到,每次把两个兑换名称转化为一个数,然后建边 \(a \to b\),边权为汇率 \(k\)。
题目就是求边权乘积最大环(有点绕,自行理解)。
注意到 \(n\) 很小,用 Floyd 即可。
最后答案就是 \(e_{1, 1}\)。
代码
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
int n;
double e[35][35];
bool solve()
{
map <string, int> mp; //将字符串转化为值
for (int i = 1; i <= n; i++)
{
string s;
cin >> s;
mp[s] = i;
}
memset(e, -127, sizeof(e)); //double 类型,要用 -127 初始化,表示赋值无穷小
int m;
cin >> m;
while (m--)
{
string u, v; double k;
cin >> u >> k >> v;
e[mp[u]][mp[v]] = k;
}
for (int k = 1; k <= n; k++) //floyd
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
e[i][j] = max(e[i][j], e[i][k] * e[k][j]); //小改动
return e[1][1] > 1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
for (int T = 1;; T++)
{
cin >> n;
if (n == 0) break;
bool ans = solve();
cout << "Case " << T << ": ";
if (ans) cout << "Yes\n"; else cout << "No\n";
}
return 0;
}
希望能帮助到大家!