1. 程式人生 > 實用技巧 >【最短路-判斷正權環 Bellman-Ford/Floyd】Arbitrage POJ - 2240

【最短路-判斷正權環 Bellman-Ford/Floyd】Arbitrage POJ - 2240

Arbitrage POJ - 2240

題意:

給出一系列貨幣匯率,問其中有無某種貨幣能在某些兌換操作後兌換回原貨幣,並且數量比開始時增多。

思路:

將貨幣視為節點,將兌換操作視為從一個節點到另一個節點的一條單向邊。假定起點是1元,進行類似最短路的鬆弛操作後,再看起點是否多於1元即可。也就是判斷是否存在正權環

Bellman-Ford

const int maxn = 40;

int num = 0;
map<string, int> currency
struct Edge {
    int from, to;
    double dist;
};
vector<Edge> edges;
double d[maxn];
int n, m;

void init(int n) {
    num = 0;
    edges.clear();
    currency.clear();
    memset(d, 0, sizeof(d));
}

bool solve(int s) {
    memset(d, 0, sizeof(d));
    d[s] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < edges.size(); j++) {
            Edge& e = edges[j];
            if (d[e.from] * e.dist > d[e.to]) {
                d[e.to] = d[e.from] * e.dist;
            }
        }
    }
    if (d[s] > 1.0) return true;
    return false;
}

int main()
{
   // ios::sync_with_stdio(false);
   /// int t; cin >> t; while (t--) {
    int kase = 0;
    while (cin >> n && n) {
        init(n);
        for (int i = 1; i <= n; i++) {
            string s;
            cin >> s;
            currency[s] = i;
        }
        cin >> m;

        for (int i = 1; i <= m; i++) {
            string u, v;
            double dis;
            cin >> u >> dis >> v;
            Edge t;
            t.from = currency[u];
            t.to = currency[v];
            t.dist = dis;
            edges.push_back(t);
        }

        int ok = 0;

        for (int i = 1; i <= n; i++) {
            if (solve(i)) {
                ok = 1;
                break;
            }
        }
        cout << "Case " << ++kase << ": ";
        if (!ok) cout << "No" << endl;
        else cout << "Yes" << endl;
    }
   // }
    return 0;
}

Floyd

int n, m;
map<string, int> currency;
double edges[maxn][maxn];
double d[maxn];
double temp[maxn];

bool floyd() {
    for (int i = 1; i <= n; i++) {
        temp[i] = d[i];
    }
    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (d[i] * edges[i][j] > d[j]) {
                    d[j] = d[i] * edges[i][j];
                }
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        if (d[i] > temp[i]) return true;
    }
    return false;
}

int main()
{
    // ios::sync_with_stdio(false);
    /// int t; cin >> t; while (t--) {
    int kase = 0;
    while (cin >> n && n) {
        memset(edges, INF, sizeof(edges));
        for (int i = 1; i <= n; i++) d[i] = 1;
        for (int i = 1; i <= n; i++) {
            string s;
            cin >> s;
            currency[s] = i;
        }
        cin >> m;
        for (int i = 1; i <= m; i++) {
            string u, v;
            double dis;
            cin >> u >> dis >> v;
            edges[currency[u]][currency[v]] = dis;
        }
        floyd();
        cout << "Case " << ++kase << ": ";
        if (floyd()) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}