POJ-2240 Arbitrage---判断正环+枚举
题目链接:
https://vjudge.net/problem/POJ-2240
题目大意:
已知n种货币,以及m种货币汇率及方式,问能否通过货币转换,使得财富增加。
思路:
由于这里问的是财富有没有增加,但是没有源点,所以可以枚举1-n为源点,分别用bellman-ford算法判断是否存在正环,如果有正环那就输出Yes,反之输出No。
这里还需要编号
其实可以用Floyd算法直接出结果判断有没有正环,这里用bellman-ford是卡着时间过的。
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<set> 10 #include<sstream> 11 using namespace std; 12 typedef long long ll; 13 const int maxn = 1000 + 10; 14 const int INF = 1 << 25; 15 int T, n, m, cases, tot; 16 map<string, int>id; 17 set<string>cnt; 18 struct edge 19 { 20 int u, v; 21 double r; 22 edge(int u, int v, double r):u(u), v(v), r(r){} 23 edge(){} 24 }; 25 edge a[maxn]; 26 int getid(string s) 27 { 28 if(cnt.count(s))return id[s]; 29 cnt.insert(s); 30 return id[s] = cnt.size(); 31 } 32 double d[maxn]; 33 bool Bellman(int u) 34 { 35 for(int i = 1; i <= n; i++)d[i] = 1.0 * INF; 36 d[u] = 1; 37 for(int i = 0; i < n; i++) 38 { 39 for(int j = 0; j < tot; j++) 40 { 41 int x = a[j].u, y = a[j].v; 42 double r = a[j].r; 43 if(d[x] * r > d[y]) 44 { 45 d[y] = d[x] * r; 46 if(i == n - 1)return true;//第n次迭代还有更新说明存在正环 47 } 48 } 49 } 50 return false; 51 } 52 int main() 53 { 54 while(cin >> n && n) 55 { 56 string s; 57 cnt.clear(); 58 id.clear(); 59 tot = 0; 60 bool flag = 0; 61 for(int i = 0; i < n; i++) 62 { 63 cin >> s; 64 getid(s); 65 } 66 cin >> m; 67 string s1, s2; 68 double r; 69 for(int i = 0; i < m; i++) 70 { 71 cin >> s1 >> r >> s2; 72 int u = getid(s1); 73 int v = getid(s2); 74 a[tot++] = edge(u, v, r); 75 } 76 printf("Case %d: ", ++cases); 77 for(int i = 1; i <= n; i++) 78 { 79 if(Bellman(i)) 80 { 81 flag = 1; 82 break; 83 } 84 } 85 if(flag)printf("Yes\n"); 86 else printf("No\n"); 87 } 88 return 0; 89 }
越努力,越幸运