トピックリンク:POJ 1860
説明
いくつかの通貨の為替ポイントは、私たちの街で働いています。私たちは、各ポイントは2つの特定の通貨を専門と実行するだけでこれらの通貨での操作を交換することを想定してみましょう。通貨の同じペアに特化したいくつかのポイントが存在する場合があります。各点はBにAの為替レートは、あなたが1Aのために取得するBの量であり、独自の為替レートを持っています。また、各交換ポイントはいくつかの手数料、あなたの交換作業のために支払わなければならない合計を持っています。委員会は、常にソース通貨で収集されます。
たとえば、あなたが交換ポイントにロシア・ルーブルに100ドルを交換したい場合は、どこ為替レートは29.75で、手数料は0.39であるあなたは、(100から0.39)を取得します* = 2963.3975RUR 29.75。
あなたは確かにあなたが私たちの街に対処することができ、N個の異なる通貨があることを知っています。私たちは1からNまでの各通貨に一意の整数番号を割り当ててみましょう。為替レートおよび手数料をそれぞれAとB、BにAを交換する - それ通貨交換、及び実際のRAB、CAB、RBAおよびCBAの数 - A整数およびB:各交換点は6つの数字で記述することができます。
彼は何とか、いくつかの交換作業の後、彼の資本を増やすことができれば、ニックは、通貨Sと不思議にいくつかのお金を持っています。もちろん、彼は最終的に通貨Sに彼のお金を持って望んでいます。この困難な質問に答えるために彼を助けます。彼の操作をしながらニックは常にお金の非負の和を持っている必要があります。
入力
- 通貨の数、M - 交換ポイント数、S - 通貨ニックの数があり、V - 、彼が持っている通貨単位の量N:入力の最初の行は、4つの数字を含んでいます。対応する交換点の説明 - - 順上で指定の次のMラインが6つの番号をそれぞれ含みます。数値は、1つ以上のスペースで区切られます。1 <= S <= N <= 100、1 <= M <= 100、Vは実数、0 <= V <= 103です。
為替レートと手数料が実数である各点について、小数点、10-2 <=レート<= 102、0 <=手数料<= 102の後に最大で2桁の所与。
何の交換ポイントがよりこの順序で何度も使用されていない場合、私たちは為替操作の簡単ないくつかのシーケンスを呼ぶことにしましょう。あなたは、最後に合計の数値の比をとることができるし、為替業務のいずれかの簡単なシーケンスの始めに少ない104以上になります。
出力
ニックは、出力ファイルに他のケースの出力NOで、出力YESを彼の富を増やすことができます。
サンプル入力
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00
サンプル出力
YES
ソース
解決
問題の意味
そこ\(N \)の通貨、為替レートおよび2つの通貨間のいくつかの税の価格を与えます。
償還プロセスの一部が保持しているオリジナルの通貨は価値の増加を作るかどうかを確認して下さい。
思考
通貨などノード、有向エッジなどの交換処理、その結果、実際には問題は、図の正のループが存在するか否かが判定されます。
使用\(ベルマン・フォード\)と同様の方法のアルゴリズム、および負のリングを決定するには、条件の変化を緩和することができます。注初期化も変更する必要があります。
コード
#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1e3;
const double eps = 1e-8;
int n, m, s;
double v;
int tot;
double dis[maxn];
struct Edge {
int from, to;
double r, c;
Edge(int f = 0, int t = 0, double r = 0, double c = 0): from(f), to(t), r(r), c(c) {}
} edges[maxn];
void add(int f, int t, double r, double c) {
edges[tot++] = Edge(f, t, r, c);
}
bool Bellman_Ford() {
memset(dis, 0, sizeof(dis));
dis[s] = v;
for(int i = 1; i <= n - 1; ++i) {
bool flag = false;
for(int j = 0; j < tot; ++j) {
int f = edges[j].from, t = edges[j].to;
double r = edges[j].r, c = edges[j].c;
double tmp = (dis[f] - c) * r;
if(dis[t] < tmp) {
dis[t] = tmp;
flag = true;
}
}
if(!flag) {
break;
}
}
for(int i = 0; i < tot; ++i) {
if(dis[edges[i].to] < (dis[edges[i].from] - edges[i].c) * edges[i].r) {
return true;
}
}
return false;
}
int main() {
while(~scanf("%d%d%d%lf", &n, &m, &s, &v)) {
tot = 0;
int f, t;
double r1, c1, r2, c2;
for(int i = 0; i < m; ++i) {
scanf("%d%d%lf%lf%lf%lf", &f, &t, &r1, &c1, &r2, &c2);
add(f, t, r1, c1);
add(t, f, r2, c2);
}
if(Bellman_Ford()) {
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}