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;
            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
*/



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