标签:
题目大意:有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的
怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)
解题思路:单源最短路径算法,因为题目可能存在负边,所以用Bellman Ford算法,
原始Bellman Ford可以用来求负环,这题需要改进一下用来求正环
本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,
求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。
因此初始化dis(S)=V 而源点到其他点的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,
说明存在最大路径;如果可以一直变大,说明存在正环。判断是否存在环路,用Bellman-Ford和spfa都可以。
AC代码:
1 #include <stdio.h> 2 #include <string.h> 3 double dis[110]; 4 int n,m,s,ans; 5 double v; 6 struct data 7 { 8 int x,y; 9 double r,c; 10 }num[220]; 11 void add(int a,int b,double c,double d) 12 { 13 num[ans].x = a; 14 num[ans].y = b; 15 num[ans].r = c; 16 num[ans].c = d; 17 ans ++; 18 } 19 bool Bellman_ford() 20 { 21 int i,j; 22 for (i = 1; i <= n; i ++) //此处与Bellman-Ford的处理相反,初始化为源点到各点距离0,到自身的值为原值 23 dis[i] = 0; 24 dis[s] = v; 25 bool flag; 26 for (i = 1; i < n; i ++) 27 { 28 flag = false; //优化 29 for (j = 0; j < ans; j ++) 30 if (dis[num[j].y] < (dis[num[j].x]-num[j].c)*num[j].r) //注意是小于号 31 { 32 dis[num[j].y] = (dis[num[j].x]-num[j].c)*num[j].r; 33 flag = true; 34 } 35 if (!flag) //如果没有更新,说明不存在正环 36 return false; 37 } 38 for (j = 0; j < ans; j ++) //正环能够无限松弛 39 if (dis[num[j].y] < (dis[num[j].x]-num[j].c)*num[j].r) 40 return true; //有正环 41 return false; 42 } 43 int main () 44 { 45 int i,j; 46 int a,b; 47 double r1,c1,r2,c2; 48 while (~scanf("%d%d%d%lf",&n,&m,&s,&v)) 49 { 50 ans = 0; 51 for (i = 0; i < m; i ++) 52 { 53 scanf("%d%d%lf%lf%lf%lf",&a,&b,&r1,&c1,&r2,&c2); 54 add(a,b,r1,c1); 55 add(b,a,r2,c2); 56 } 57 if (Bellman_ford()) 58 printf("YES\n"); 59 else 60 printf("NO\n"); 61 } 62 return 0; 63 }
SPFA算法:
1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 using namespace std; 5 const int N = 110; 6 int n, m, s; 7 double dis[N], v, rate[N][N], cost[N][N]; 8 9 bool spfa(int start) 10 { 11 bool inq[110]; 12 memset(inq, 0, sizeof(inq)); 13 memset(dis, 0, sizeof(dis)); 14 dis[start] = v; 15 queue<int> Q; 16 Q.push(start); 17 inq[start] = true; 18 while(!Q.empty()) 19 { 20 int x = Q.front(); 21 Q.pop(); 22 inq[x] = false; 23 for(int i = 0; i <= n; i++) 24 { 25 if(dis[i] < (dis[x] - cost[x][i]) * rate[x][i]) 26 { 27 dis[i] = (dis[x] - cost[x][i]) * rate[x][i]; 28 if(dis[start] > v) 29 return true; 30 if(!inq[i]) 31 { 32 Q.push(i); 33 inq[i] = true; 34 } 35 } 36 } 37 } 38 return false; 39 } 40 41 int main() 42 { 43 int i, j; 44 while(~scanf("%d%d%d%lf",&n,&m,&s,&v)) 45 { 46 int a, b; 47 double rab, rba, cab, cba; 48 for(i = 1; i <= n; i++) 49 for(j = 1; j <= n; j++) 50 { 51 if(i == j) 52 rate[i][j] = 1; 53 else 54 rate[i][j] = 0; 55 cost[i][j] = 0; 56 } 57 for(i = 0; i < m; i++) 58 { 59 scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba); 60 rate[a][b] = rab; 61 rate[b][a] = rba; 62 cost[a][b] = cab; 63 cost[b][a] = cba; 64 } 65 if(spfa(s)) 66 printf("YES\n"); 67 else 68 printf("NO\n"); 69 } 70 return 0; 71 }
POJ 1860 Currency Exchange (最短路)
标签:
原文地址:http://www.cnblogs.com/yoke/p/5875852.html