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\n"); 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\n"); 85 else printf("NO\n"); 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 }
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。