题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66569#problem/E
题目描述:有几种钞票,钞票间有几种互换方式(也就是常见的汇率),同样兑换时要缴纳手续费,问是否存在一种情况使兑换后所得钱比之前更多
题目思路:其实就是判断是否能够无限兑换钞票的问题(使钱不断增加的方法),可以用bellman-ford稍加改变即可。
AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson root<<1,l,mid #define rson root<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) using namespace std; #define gamma 0.5772156649015328606065120 //欧拉常数 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 10100000 #define maxn 1000100 typedef long long LL; typedef pair<int,int> PII; int start,n,m,head[101],index; double d[101],money; struct Node{ int x,y; ///起点终点 double price; ///兑换的比率 double cost; ///手续费 }node[300]; void add(int &x,int &y,double &p,double &v) ///加边 { node[index].x=x; node[index].y=y; node[index].price=p; node[index++].cost=v; } bool _solve() ///bellman-ford算法的改用 { int i,j; memset(d,0,sizeof(d)); d[start]=money; for(i=1; i<=n; ++i) { for(j=0; j<index; ++j) { int pos1=node[j].x,pos2=node[j].y; double temp=(d[pos1]-node[j].cost)*node[j].price; ///兑换后所得的钱 if(temp>d[pos2]) d[pos2]=temp; } } for(int j=0; j<index; ++j) ///查找是否有正权值环 { int pos1=node[j].x,pos2=node[j].y; double temp=(d[pos1]-node[j].cost)*node[j].price; if(temp>d[pos2]) return true; } return false; } int main() { int pos,i,j,group,x,y; double v1,v2; while(scanf("%d%d%d%lf",&n,&m,&start,&money)!=EOF) ///start最开始有哪种钞票,money最开始有多少钱 { index=0; for(i=0; i<m; ++i) { scanf("%d%d",&x,&y); scanf("%lf%lf",&v1,&v2); add(x,y,v1,v2); scanf("%lf%lf",&v1,&v2); add(y,x,v1,v2); } if(_solve()) puts("YES"); else puts("NO"); } return 0; }
下面是SPFA版本
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson root<<1,l,mid #define rson root<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) using namespace std; #define gamma 0.5772156649015328606065120 //欧拉常数 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 1001000 #define maxn 300000 typedef long long LL; typedef pair<int,int> PII; struct Node{ int y; ///终点 double p,c; ///兑换比率 以及 兑换所交手续费 int next; ///下个节点 }node[300];int n_cnt=0; int l[105]; ///头节点 double d[105]; ///最大兑换金额 int vis[105]; void init() { memset(l,-1,sizeof(l)); n_cnt=0; } double get(double &mo,int &cnt) ///可得兑换金额 { double temp=(mo-node[cnt].c)*node[cnt].p; return temp; } int spfa(int &n,int &s,double &mo) { int index[105]; memset(index,0,sizeof(index)); memset(d,0,sizeof(d)); memset(vis,0,sizeof(vis)); d[s]=mo; int i,j;double pri,co; queue<int>q; q.push(s); while(!q.empty()) { i=q.front();q.pop(); /// i是起点 if(++index[i]>n) return 1; ///入队n次则有环路 vis[i]=0; ///出队标志 for(j=l[i]; j!=-1; j=node[j].next) { int pos=node[j].y; double temp=get(d[i],j); if(temp>d[pos]) { d[pos]=temp; if(!vis[pos]) { vis[pos]=1; q.push(pos); } } } } return 0; } void add(int &x,int &y,double &p,double &c) ///邻接表加边 { node[n_cnt].y=y; node[n_cnt].p=p; node[n_cnt].c=c; node[n_cnt].next=l[x]; l[x]=n_cnt++; } int main() { int i,j,group,x,y,m,start; double money,price,cost; //freopen("lxx.txt","r",stdin); while(scanf("%d%d%d%lf",&group,&m,&start,&money)!=EOF) { init(); for(i=0; i<m; ++i){ scanf("%d%d%lf%lf",&x,&y,&price,&cost); add(x,y,price,cost); scanf("%lf%lf",&price,&cost); add(y,x,price,cost); } if(spfa(group,start,money)) printf("YES "); else printf("NO "); } return 0; }
加油!!!