[POJ1860]Currency Exchange

 

每一种货币都可以视为一个节点,而每一个exchange point都视为提供了两条有向边(这意味着从起点出发总是能回到起点),据此可以构建一张有向图.

求解的问题是,是否存在路径使得从起点出发再回到起点,总资产增加.

会发现如果存在这样的一条路径,那么可以通过不断地走这条路径使得资产达到无限多,这意味着只需要判断图中是否存在一个"正环",只需要借鉴Bellman-Ford判负环的方法.

不过这里求的不是最短路,而是最大值,那么改一下计算公式即可:

double d = (dist[cur] - it->C) * it->R;
            if (dist[it->to] < d) {
("松弛"操作)... ...
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

struct E {
    int to;
    double R, C;
};
vector<E> e[110];
int n, m, s, ct[110];
double v, dist[110];
bool used[110];

int main() {
    scanf("%d%d%d%lf", &n, &m, &s, &v);
    while (m--) {
        int A, B;
        double Rab, Cab, Rba, Cba;
        scanf("%d%d%lf%lf%lf%lf", &A, &B, &Rab, &Cab, &Rba, &Cba);
        e[A].push_back({B, Rab, Cab});
        e[B].push_back({A, Rba, Cba});
    }

    queue<int> q;
    q.push(s);
    used[s] = true;
    dist[s] = v;
    while (!q.empty()) {
        int cur = q.front();
        q.pop();
        used[cur] = false;
        if (++ct[cur] >= n) {
            puts("YES");
            return 0;
        }

        for (vector<E>::iterator it = e[cur].begin(); it != e[cur].end(); it++) {
            double d = (dist[cur] - it->C) * it->R;
            if (dist[it->to] < d) {
                dist[it->to] = d;
                if(!used[it->to]){
                    used[it->to] = true;
                    q.push(it->to);
                }
            }
        }
    }

    puts("NO");

    return 0;
}
POJ 1860

 

posted @ 2021-04-06 14:16  goverclock  阅读(75)  评论(0编辑  收藏  举报