标签:exchange pac spec sep href art ssi bellman main
题目链接:
https://cn.vjudge.net/problem/POJ-1860
3 2 1 20.0 1 2 1.00 1.00 1.00 1.00 2 3 1.10 1.00 1.10 1.00Sample Output
YES
1 /* 2 题意描述 3 输入货币的种数n,货币兑换点数m,某人有货币种类s,价值hm 4 m个兑换点的规则是a兑换b,汇率是rab,费用是cab,b兑换a,汇率是rba,费用是cba,计算规则是(va-cab)*rab 5 问能否通过这m个兑换点使他的拥有s这种货币的钱数增加 6 7 解题思路 8 不管怎么兑换,关键是最后还要换回s这种钱,那么必须至少存在一个环,使得最后还能换回s,但是又要求增加钱数,那么这个换必须是正 9 环。所以问题变成了如何判断图中存在正环。使用Bellman_Ford算法判断正环即可。 10 11 样例中第二条边是1.10 不是1.00,看样例看了半天没看懂 12 注意函数调用时数据类型的变换,包括输入和函数传递参数时的数据类型 13 */ 14 #include<cstdio> 15 #include<cstring> 16 const int maxn = 410; 17 18 int u[maxn], v[maxn]; 19 double ruv[maxn], cuv[maxn], dis[maxn]; 20 int n, m, en;//边数 21 bool Bellman_Ford(int s, double hm); 22 23 int main() 24 { 25 int a, b, s; 26 double hm, rab, cab, rba, cba; 27 while(scanf("%d%d%d%lf", &n, &m, &s, &hm) != EOF) { 28 en = 0; 29 for(int i = 1; i <= m; i++) { 30 scanf("%d%d%lf%lf%lf%lf", &a, &b, &rab, &cab, &rba, &cba); 31 u[en] = a; v[en] = b; 32 ruv[en] = rab; 33 cuv[en++] = cab; 34 35 u[en] = b; v[en] = a; 36 ruv[en] = rba; 37 cuv[en++] = cba; 38 } 39 40 if(Bellman_Ford(s, hm)) 41 puts("YES"); 42 else 43 puts("NO"); 44 } 45 return 0; 46 } 47 48 bool Bellman_Ford(int s, double hm) { 49 memset(dis, 0, sizeof(dis)); 50 dis[s] = hm; 51 52 for(int i = 1; i <= n; i++) { 53 for(int j = 0; j < en; j++) { 54 if(dis[v[j]] < (dis[u[j]] - cuv[j]) * ruv[j]) { 55 dis[v[j]] = (dis[u[j]] - cuv[j]) * ruv[j]; 56 if(i == n) 57 return 1;//存在正环 58 } 59 } 60 } 61 return 0; 62 }
使用结构体封装一下Bellman-Ford算法,再使用队列和邻接表优化一下,代码如下:
使用的时候注意数据类型的使用和结点数全部减1。
1 #include<cstdio> 2 #include<vector> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 7 const int maxn = 310; 8 9 struct Edge { 10 int from, to; 11 double rait, com; 12 Edge(int u, int v, double r, double c): from(u), to(v), rait(r), com(c) { } 13 }; 14 15 struct Bellman_Ford { 16 int n, m, s; 17 double hm; 18 vector<Edge> edges; 19 vector<int> G[maxn]; 20 double d[maxn]; 21 bool inq[maxn]; 22 int cnt[maxn]; 23 24 void init(int n) { 25 this->n = n; 26 for(int i = 0; i < n; i ++) { 27 G[i].clear(); 28 } 29 edges.clear(); 30 } 31 32 void AddEdge(int from, int to, double rait, double com){ 33 edges.push_back(Edge(from, to, rait, com)); 34 m = edges.size(); 35 G[from].push_back(m - 1); 36 } 37 38 bool bellman_ford (int s, double hm) { 39 this->s = s; 40 this->hm = hm; 41 memset(d, 0, sizeof(d)); 42 d[s] = hm; 43 44 memset(inq, 0, sizeof(inq)); 45 memset(cnt, 0, sizeof(cnt)); 46 47 queue<int> q; 48 q.push(s); 49 inq[s] = 1; 50 51 while(!q.empty()) { 52 int u = q.front(); 53 q.pop(); 54 55 inq[u] = 0; 56 for(int i = 0; i < G[u].size(); i++) { 57 Edge e = edges[G[u][i]]; 58 if(d[e.to] < (d[u] - e.com) * e.rait){ 59 d[e.to] = (d[u] - e.com) * e.rait; 60 if(!inq[e.to]) { 61 q.push(e.to); 62 inq[e.to] = 1; 63 64 cnt[e.to]++; 65 if(cnt[e.to] > n) 66 return 1; 67 } 68 } 69 } 70 } 71 return 0; 72 } 73 }; 74 75 struct Bellman_Ford solve; 76 int main() 77 { 78 int s, a, b, n, m; 79 double hm, rab, cab, rba, cba; 80 while(scanf("%d%d%d%lf", &n, &m, &s, &hm) != EOF) { 81 solve.init(n); 82 for(int i = 1; i <= m; i++) { 83 scanf("%d%d%lf%lf%lf%lf", &a, &b, &rab, &cab, &rba, &cba); 84 a--; 85 b--; 86 solve.AddEdge(a, b, rab, cab); 87 solve.AddEdge(b, a, rba, cba); 88 } 89 int ans = solve.bellman_ford(s-1,hm); 90 91 if(ans) 92 puts("YES"); 93 else 94 puts("NO"); 95 } 96 return 0; 97 }
POJ 1860 Currency Exchange(如何Bellman-Ford算法判断正环)
标签:exchange pac spec sep href art ssi bellman main
原文地址:https://www.cnblogs.com/wenzhixin/p/9383074.html