# POJ ~ 2240 ~ ambitrace (Floyd or BellmanFord)

You now have N types of currencies. There are m exchange rate relationships between these N types of currencies. Then enter the group M relationship, A, rate, B, which means that A currency can be exchanged for B currency of rate per unit. Do you have any way to increase your money?

Idea: judge whether the ring is positive. The currency type is mapped to a number with MAP and then mapped. Set all your currencies to a principal of 1. Then Floyd ran to see if there was any money that made him a lot more. Or run Bellman Ford N times to see if there is a positive ring. When the relaxation condition is changed to that the weight can be increased, it can be relaxed.

Pit: pay attention to C + +, G + + may timeout.

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 (queue optimization 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*/;       //Start, end, distance
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;                      //Number of nodes and sides (including reverse arc)
vector<Edge> edges;            //Side table. edges[e] and edges[e^1] are opposite arcs to each other
vector<int> G[MAXN];           //Adjacency table, G[i][j] indicates the serial number of the j-th edge of node i in the edges array
bool vis[MAXN];                //In queue or not
//int d[MAXN];                   //Bellman-Ford
double d[MAXN];
int p[MAXN];                   //Previous arc
int cnt[MAXN];                 //Team entry times

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;//Negative ring
}
}
}
}
return true;//No negative ring
}
};
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;
}
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
*/
```

Posted by jasonyoung on Sat, 02 May 2020 01:32:36 -0700