第一次做图论的题,所以如果下面的话有说的不对的还请见谅。
题目概述:
我们的主人公是一个套利商人,通过在各个零钱兑换点来回来去换钱来得到最大的利润,零钱点的信息有零钱兑换率,手续费。我们只需要判断最后他手里的钱是不是能增加就好了。思想就在于算“正权环”。
算法思想:
我们用Bellman-Ford来做这道题,模型化的方法就是每一种货币当作图的一个点,每一种exchange station作为一条边,边要记载着从哪里,到哪里,change_rate以及手续费。开一个struct来记载这些信息。然后这样组成一张图。
更新每一张图,d[e[j].to]相当于如果当前change之后所拥有的钱,(d[e[j].from]-e[j].rate)*d[j].com相当于新路之后所拥有的钱,然后比较大小如果大的话就更新。model之后相当于是那个图的最长路径。
应该就是一个非常naive的算法,只是我是初学所以不太了解,最后真正的代码和Bellman-Ford的伪代码都十分相似。
交到OJ之后是140多MS,查题解的时候发现有各种十几MS的应该就是所谓的SPFA做的吧。
代码部分:
#include <iostream> using namespace std; struct edge{ int from, to; double rate, com; }; edge e[217]; double d[117]; int n, m,s; double v; int main() { cin >> n >> m >> s >> v; for (int i = 0; i < m * 2; i += 2){ int tmp_from, tmp_to; double tmp_rate, tmp_com; cin >> tmp_from >> tmp_to >> tmp_rate >> tmp_com; e[i].from = tmp_from; e[i].to = tmp_to; e[i].rate = tmp_rate; e[i].com = tmp_com; cin >> tmp_rate >> tmp_com; e[i + 1].from = tmp_to; e[i + 1].to = tmp_from; e[i + 1].rate = tmp_rate; e[i + 1].com = tmp_com; } d[s] = v; //Bellman-ford algorithm for (int i = 0; i < n-1; i++){ for (int j = 0; j < 2 * m; j++){ if (d[e[j].to] < (d[e[j].from] - e[j].com)*e[j].rate) { d[e[j].to] = (d[e[j].from] - e[j].com)*e[j].rate; } } } bool flag = false; for (int j = 0; j < 2 * m; j++){ if (d[e[j].to] < (d[e[j].from] - e[j].com)*e[j].rate) { flag = true; break; } } if (flag) cout << "YES" << endl; else cout << "NO" << endl; return 0; }