POJ-1860 Currency Exchange---Bellman-Ford判斷正環
題目鏈接:
https://vjudge.net/problem/POJ-1860
題目大意:
我們的城市有幾個貨幣兌換點。讓我們假設每一個點都只能兌換專門的兩種貨幣。可以有幾個點,專門從事相同貨幣兌換。每個點都有自己的匯率,外匯匯率的A到B是B的數量你1A。同時各交換點有一些傭金,你要為你的交換操作的總和。在來源貨幣中總是收取傭金。
例如,如果你想換100美元到俄羅斯盧布兌換點,那裏的匯率是29.75,而傭金是0.39,你會得到(100 - 0.39)×29.75=2963.3975盧布。
你肯定知道在我們的城市裏你可以處理不同的貨幣。讓每一種貨幣都用唯一的一個小於N的整數表示。然後每個交換點,可以用6個整數表描述:整數a和b表示兩種貨幣,a到b的匯率,a到b的傭金,b到a的匯率,b到a的傭金。
nick有一些錢在貨幣S,他希望能通過一些操作(在不同的兌換點兌換),增加他的資本。當然,他想在最後手中的錢仍然是S。幫他解答這個難題,看他能不能完成這個願望。
輸入數據:
第一行四個數,N,表示貨幣的總數;M,兌換點的數目;S,nick手上的錢的類型;V,nick手上的錢的數目;1<=S<=N<=100, 1<=M<=100, V 是一個實數 0<=V<=103.
接下來M行,每行六個數,整數a和b表示兩種貨幣,a到b的匯率,a到b的傭金,b到a的匯率,b到a的傭金(0<=傭金<=102,10-2<=匯率<=102)
輸出數據:
如果nick能夠實現他的願望,則輸出YES,否則輸出NO。
思路:
這是bellman-ford算法的逆運用,首先初始化的時候dist數組全部為0,而源點的dist為題目給定的初始錢的數目,每次松弛的時候往大的方向松弛,而且松弛的時候是乘而不是加。直接判斷第n次松弛時是否有更新。有更新說明存在正環
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8#include<map> 9 #include<sstream> 10 using namespace std; 11 typedef long long ll; 12 const int maxn = 200 + 10; 13 const int INF = 1 << 25; 14 int T, n, m, cases; 15 struct money 16 { 17 int u, v; 18 double r, c;//r為匯率,c為手續費 19 money(){} 20 money(int u, int v, double r, double c):u(u), v(v), r(r), c(c){} 21 }; 22 money e[maxn]; 23 double d[maxn]; 24 int tot; 25 bool bellman(int u, double s)//u為源點,s為最初有的錢 26 { 27 memset(d, 0, sizeof(d));//這裏需要正環,初始化時賦值為0 28 d[u] = s;//源點初始化成1 29 for(int i = 0; i < n; i++)//n次叠代 30 { 31 for(int j = 0; j < tot; j++) 32 { 33 int x = e[j].u, y = e[j].v; 34 double r = e[j].r, c = e[j].c; 35 if((d[x] - c) * r > d[y])//如果松弛結果更大,更新 36 { 37 d[y] = (d[x] - c) * r; 38 if(i == n - 1)return true;//說明存在正環 39 } 40 } 41 } 42 return false; 43 } 44 int main() 45 { 46 int s, a, b;//起點s 47 double v, rab, rba, cab, cba; 48 while(cin >> n >> m >> s >> v) 49 { 50 tot = 0; 51 for(int i = 0; i < m; i++) 52 { 53 cin >> a >> b >> rab >> cab >> rba >> cba; 54 e[tot++] = money(a, b, rab, cab); 55 e[tot++] = money(b, a, rba, cba); 56 } 57 if(bellman(s, v))cout<<"YES"<<endl; 58 else cout<<"NO"<<endl; 59 } 60 return 0; 61 }
POJ-1860 Currency Exchange---Bellman-Ford判斷正環