poj1860(最短路,负环)

来源:互联网 发布:淘宝不搜血滴子上一句 编辑:程序博客网 时间:2024/05/23 14:52
/*translation:给出若干货币,以及货币之间的转换方法。假设知道A->B:r=29.75,c=0.39。则由100货币A转换为B为B=(100 - 0.39) * 29.75 。现在给你一种特定的货币以及每种货币间的r和c,求其能否通过某种转换方式使得最终转换为本来货币时,资产增加?solution:最短路径的bellmanFord算法,判断负环。可以设dis[i]为转换到i货币时的最大资产,则本质上就是一个最长路径。这样一来跟求单源最短路径其实也没什么区别。题目问能否使得资产增加,这就可以联想到在最短路径中求负环的问题,普通单源最短路径中的负环使得在经过该环时回到源点的路径更短。而对应到此题也是同样的道理,就是求是否存在一个环使得兑换到原货币时资产增加。如此利用bellmanFord算法就可以轻松解出来。note:date:2016.8.21*/#include <iostream>#include <cstdio>#include <vector>#include <cstring>#include <queue>using namespace std;const int maxn = 101;const int INF = 1 << 30;struct Edge {int from, to;double r, c;Edge(int f, int t, double r, double c) : from(f), to(t), r(r), c(c) {}Edge() {}};vector<Edge> edges;vector<int> G[maxn];int n, m, s, cnt[maxn];double dis[maxn], v;//到了i点的资金数量bool inq[maxn];void addEdge(int from, int to, double r1, double c1, double r2, double c2) {edges.push_back(Edge(from, to, r1, c1));edges.push_back(Edge(to, from, r2, c2));int len = edges.size();G[from].push_back(len-2);G[to].push_back(len-1);}bool bellmanFord(int s) {queue<int> q;memset(inq, 0, sizeof(inq));memset(cnt, 0, sizeof(cnt));for(int i = 1; i <= n; i++)    dis[i] = -INF;dis[s] = v;inq[s] = true;q.push(s);while(!q.empty()) {int u = q.front();q.pop();inq[u] = false;for(int i = 0; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(dis[u] > -INF && dis[e.to] < (dis[u] - e.c) * e.r) {dis[e.to] = (dis[u] - e.c) * e.r;if(!inq[e.to]) {q.push(e.to);inq[e.to] = true;if(++cnt[e.to] > n)return false;}}}}return true;}int main(){//freopen("in.txt", "r", stdin);    while(~scanf("%d%d%d%lf", &n, &m, &s, &v)) {edges.clear();for(int i = 0; i < maxn; i++)G[i].clear();int from, to;double r1, c1, r2, c2;for(int i = 0; i < m; i++) {scanf("%d%d%lf%lf%lf%lf", &from, &to, &r1, &c1, &r2, &c2);addEdge(from, to, r1, c1, r2, c2);}if(!bellmanFord(s))printf("YES\n");elseprintf("NO\n");    }    return 0;}

0 0
原创粉丝点击