/*
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");
else printf("NO\n");
}
return 0;
}
poj1860(最短路,负环)
最新推荐文章于 2023-02-18 15:40:19 发布