POJ——T1860 Currency Exchange

http://poj.org/problem?id=1860

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 29874   Accepted: 11251


题目大意:

´有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加。  
 
 题解:
´货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的。 
所以用SPFA求正环就可以了
 
DFS求环法:
 1 #include <cstring>
 2 #include <cstdio>
 3 
 4 #define dou double
 5 #define INF 1<<29
 6 #define MAX(a,b) ( a>b ?a :b )
 7 
 8 using namespace std;
 9 
10 const int N(10015);
11 int n,m,s,u,v;
12 dou money,uvr,uvl,vur,vul;
13 int head[N],sumedge;
14 struct Edge
15 {
16     int to,next;
17     dou rate,lose;
18     Edge(int to=0,int next=0,dou rate=0.00,dou lose=0.00) :
19         to(to),next(next),rate(rate),lose(lose) {}
20 }edge[N<<1];
21 
22 void ins(int from,int to,dou rate,dou lose)
23 {
24     edge[++sumedge]=Edge(to,head[from],rate,lose);
25     head[from]=sumedge; 
26 }
27 
28 dou change_money(dou x,dou rate,dou lose)
29 {     return (x-lose)*rate ;    }
30 
31 int vis[N],if_YES;
32 dou dis[N];
33 
34 void SPFA(int now)
35 {
36     vis[now]=1;
37     if(if_YES) return ;
38     for(int i=head[now];i;i=edge[i].next)
39     {
40         int go=edge[i].to;
41         dou rate=edge[i].rate,lose=edge[i].lose;
42         dou cmoney=change_money(dis[now],rate,lose);
43         if(cmoney>dis[go])
44         {
45             if(vis[go])
46             {
47                 if_YES=true;
48                 break ;
49             }
50             dis[go]=cmoney;
51             SPFA(go);
52         }
53     }
54     vis[now]=0;
55     return ;
56 }
57 
58 void init(int n)
59 {
60     if_YES=sumedge=0;
61     memset(dis,0,sizeof(dis));
62     memset(head,0,sizeof(head));
63 }
64 
65 int main()
66 {
67 //    freopen("made.txt","r",stdin);
68 //    freopen("myout.txt","w",stdout);
69     
70     while(~scanf("%d%d%d%lf",&n,&m,&s,&money))
71     {
72         if(s>n)
73         {
74             printf("NO
");
75             continue;
76         }
77         init(n);
78         for(;m;m--)
79         {
80             scanf("%d%d%lf%lf%lf%lf",&u,&v,&uvr,&uvl,&vur,&vul);
81             ins(u,v,uvr,uvl); ins(v,u,vur,vul);
82         }
83         dis[s]=money; SPFA(s);
84         if(if_YES) printf("YES
");
85         else printf("NO
");
86     }
87     return 0;
88 }

BFS求环法:

 
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 int u,v,w;
 8 const int maxn = 1011;
 9 const int maxm = 10011;
10 const int oo = 1<<29;
11 struct node
12 {
13     int u;
14     int v;
15     double x,y ;
16     int next;
17 }edge[maxm];
18 double dis[maxn];
19 int m,n,num;
20 double ount;
21 int head[maxn],cnt,sum[maxn];
22 int vis[maxn] = {0};
23 queue<int>qu;
24 void add(int u,int v,double x,double y)
25 {
26     edge[cnt].u = u ;
27     edge[cnt].v = v ;
28     edge[cnt].x = x ;
29     edge[cnt].y = y ;
30     edge[cnt].next = head[u];
31     head[u] = cnt++ ;
32 }
33 int spfa(int s)
34 {
35     for(int i = 0 ; i < m ; i++)
36     {
37         dis[i] = 0;
38         vis[i] = 0 ;
39     }
40     dis[s] = ount;
41     qu.push(s);
42     vis[s] = 1 ;
43     while(!qu.empty())
44     {
45         int u = qu.front();
46         qu.pop();
47         vis[u] = 0;
48         for(int i = head[u] ; i != -1 ; i = edge[i].next)
49         {
50             int v = edge[i].v;
51             if((dis[u]-edge[i].y)*edge[i].x > dis[v])
52             {
53                 dis[v] = (dis[u]-edge[i].y)*edge[i].x;
54                 if(!vis[v])
55                 {
56                     vis[v] = 1;
57                     qu.push(v);
58                 }
59                 sum[v]++;
60                 if(sum[v] > m)
61                 return -1;
62             }
63         }
64     }
65     return 1;
66 }
67 void Init()
68 {
69     cnt = 0 ;
70     memset(head,-1,sizeof(head));
71     memset(sum,0,sizeof(sum));
72     while(!qu.empty())
73     qu.pop();
74 }
75 int main()
76 {
77     freopen("made.txt","r",stdin);
78     freopen("stdout.txt","w",stdout);
79     
80     while(scanf("%d %d %d %lf",&m,&n,&num,&ount)!=EOF)
81     {
82         Init();
83         int u,v;
84         double x,y,xx,yy ;
85         for(int i = 0 ; i < n ; i++)
86         {
87             scanf("%d %d %lf %lf %lf %lf",&u,&v,&x,&y,&xx,&yy);
88             add(u,v,x,y);
89             add(v,u,xx,yy);
90         }
91         if(spfa(num) > 0)
92         cout<<"NO"<<endl;
93         else cout<<"YES"<<endl;
94     }
95     return 0;
96 }

  

——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/6885827.html