首页 > 代码库 > poj1860(Currency Exchange)

poj1860(Currency Exchange)

题目大意:

    给你几个国家的货币兑换率,看你是否能通过不同国家的货币兑换之后是自己的财富增加,如增加输出YES,无法增加输出NO。

具体兑换过程:

   N代表几个国家,M代表几条兑换的信息,S代表起始的国家,V代表你现有的财富金额。

    从A兑换到B 得到的财富 :(V-Cab)*Rab 、

    测试数据:1 2 1.00 1.00 1.00 1.00 1.00 。代表1-2兑换的Rab、Cab是1.00 1.00.  2-1的兑换的Rab和Cab是后两位浮点数1.00 1.00。

 

解题思路:

    通过Bellman_ford 看是否有正权回路,如果有正权回路,说明财富持续增加输出YES,否则输出NO。

 

代码:

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cstdio>
  7 #include <string>
  8 #include <bitset>
  9 #include <vector>
 10 #include <queue>
 11 #include <stack>
 12 #include <cmath>
 13 #include <list>
 14 #include <map>
 15 #include <set>
 16 using namespace std;
 17 /***************************************/
 18 #define ll long long
 19 #define int64 __int64
 20 /***************************************/
 21 const int INF = 0x7f7f7f7f;
 22 const double eps = 1e-8;
 23 const double PIE=acos(-1.0);
 24 const int d1x[]= {0,-1,0,1};
 25 const int d1y[]= {-1,0,1,0};
 26 const int d2x[]= {0,-1,0,1};
 27 const int d2y[]= {1,0,-1,0};
 28 const int fx[]= {-1,-1,-1,0,0,1,1,1};
 29 const int fy[]= {-1,0,1,-1,1,-1,0,1};
 30 /***************************************/
 31 void openfile()
 32 {
 33     freopen("data.in","rb",stdin);
 34     freopen("data.out","wb",stdout);
 35 }
 36 /**********************华丽丽的分割线,以上为模板部分*****************/
 37 #define MAX 0
 38 #define N 9010
 39 int nodenum, edgenum, w; //点,边,起点
 40 typedef struct Edge //
 41 {
 42     int u, v;
 43     double c,r;
 44 } Edge;
 45 Edge edge[N];
 46 double dis[N];
 47 int d;
 48 bool Bellman_Ford(int s,double w)
 49 {
 50     for(int i = 1; i <= nodenum; ++i) //初始化
 51         dis[i]=MAX;
 52     dis[s]=w;
 53     for(int i = 1; i <= nodenum-1; ++i)
 54         for(int j=1; j<=d-1; ++j)
 55             if(dis[edge[j].u]>0&&dis[edge[j].v]<(dis[edge[j].u]-edge[j].c)*edge[j].r) //松弛(顺序一定不能反~)
 56                 dis[edge[j].v] =(dis[edge[j].u]-edge[j].c)*edge[j].r;
 57     bool flag = 0;//判断是否含有正权回路
 58     for(int j = 1; j <=d-1; ++j)
 59        if(dis[edge[j].u]>0&&dis[edge[j].v]<(dis[edge[j].u]-edge[j].c)*edge[j].r)
 60         {
 61             flag = 1;
 62             break;
 63         }
 64     return flag;
 65 }
 66 /*
 67 上边是正常的判断回路,通过至少边数N-1的循环之后,再判断下各点是否能够更新dis数组,如果更新说明出现回路。
 68 然而这题可以通过下面的方法做,原因是给你N条边但是实际记录的2*N条边,所以第一个for循环循环到2*N-1可以得出正确结果,
 69 因为超过了N-1次循环,所以足可以判断是否有正权回路,下面的bellman_ford函数的flag是判断如果后面的循环中有任意一次没
 70 进入if说明不存在正权回路,因为如果是正权回路,每一次必然会进入if。
 71 bool Bellman_Ford(int s,double w)
 72 {
 73     for(int i = 1; i <= nodenum; ++i) //初始化
 74         dis[i]=MAX;
 75     dis[s]=w;
 76     bool flag;
 77     for(int i = 1; i <= nodenum-1; ++i)
 78     {
 79         flag=true;
 80         for(int j=1; j<=d-1; ++j)
 81             if(dis[edge[j].u]>0&&dis[edge[j].v]<(dis[edge[j].u]-edge[j].c)*edge[j].r) //松弛(顺序一定不能反~)
 82             {
 83                 flag=false;
 84                 dis[edge[j].v] =(dis[edge[j].u]-edge[j].c)*edge[j].r;
 85             }
 86         if (flag)
 87             return false;
 88     }
 89     return true;
 90 }
 91 */
 92 int main()
 93 {
 94     int u,v;
 95     double c,r;
 96     int s;
 97     double w;
 98     while(scanf("%d%d%d%lf", &nodenum, &edgenum,&s,&w)!=EOF)
 99     {
100         d=1;
101         for(int i = 1; i <= edgenum; ++i)
102         {
103             scanf("%d%d%lf%lf",&u,&v,&r,&c);
104             edge[d].u=u;
105             edge[d].v=v;
106             edge[d].c=c;
107             edge[d].r=r;
108             d++;
109             scanf("%lf%lf",&r,&c);
110             edge[d].u=v;
111             edge[d].v=u;
112             edge[d].c=c;
113             edge[d].r=r;
114             d++;
115         }
116         if(Bellman_Ford(s,w))
117             printf("YES\n");
118         else
119             printf("NO\n");
120     }
121     return 0;
122 }
View Code