[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; }