poj 1806
题意:已知有n种货币,编号为1~n,以及它们之间的瑞换比例。现在Nick有第fir种货币meney元,问你Nick能不能通过这些货币的瑞换规则,使自己拿到更多的fir货币。
思路:bellman_ford。判断有没有正环,有的话Nick就可以无限次使用这个正环使自己的货币增值。
1 /** 2 * @file code.c 3 * @author <kong@KONG-PC> 4 * @date Sun Nov 04 21:54:40 2012 5 * 6 * @brief 求汇率转换问题 7 * 采用Bellman_ford算法求是否存在正环,和求最短路径相反,这里 8 * 要求最长路径,可以和典型的Bellman_ford一样,对每条边进行V-1 9 * 次松弛,然后判断是否存在正环,如果存在则表明可以增加钱数。 10 * 这里做了改进,当对每一条边进行V-1次松弛后,所得的钱数不一定 11 * 满足要求,所以需要不断松弛,结束条件有两个 12 * 1. 所有边都不能再松弛了,表明不存在正环,判断钱数是否满足条 13 * 件,返回 14 * 2. 经过不断的松弛,满足要求后,返回。 15 */ 16 #include <stdio.h> 17 #include <string.h> 18 struct{ 19 int beg, end; 20 double r, c; 21 }edge[204]; 22 23 int money, m, t; 24 double value; 25 double dis[104]; 26 27 int bell_man() 28 { 29 memset(dis, 0, sizeof(dis)); 30 dis[t] = value; 31 while(dis[t] <= value){ 32 int change=0; 33 for(int i=0;i< 2 * m; i++){ 34 if(dis[edge[i].end] < (dis[edge[i].beg] - edge[i].c) * edge[i].r){ 35 dis[edge[i].end] = (dis[edge[i].beg] - edge[i].c) * edge[i].r; 36 change=1; 37 } 38 } 39 if(!change) 40 return dis[t] > value; 41 } 42 return 1; 43 } 44 45 int main() 46 { 47 freopen("in", "r", stdin); 48 int begin, end; 49 double rn, cn, rern, recn; 50 int p=0; 51 while(scanf("%d%d%d%lf", &money, &m, &t, &value) != -1){ 52 for(int i=1;i<=m;i++){ 53 scanf("%d%d%lf%lf%lf%lf", &begin, &end, &rn, &cn, &rern, &recn); 54 edge[p].beg=begin; 55 edge[p].end=end; 56 edge[p].r=rn; 57 edge[p++].c=cn; 58 edge[p].beg=end; 59 edge[p].end=begin; 60 edge[p].r=rern; 61 edge[p++].c=recn; 62 } 63 if(!bell_man()) 64 printf("NO\n"); 65 else 66 printf("YES\n"); 67 } 68 return 0; 69 }