poj1860 - Currency Exchange

133 篇文章 0 订阅

                                   想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410
                                     转载请注明出处:
http://blog.csdn.net/wangjian8006

题目大意:有多种从a到b的汇率,在你汇钱的过程中还需要支付手续费,那么你所得的钱是 money=(nowmoney-手续费)*rate,现在问你有v钱,从s开始出发交换钱能不能赚钱

解题思路:能不能赚钱从s找一条正权回路,如果这个时候d[i]数组表示从s开始到i的最多钱,如果有一个大于v了,直接返回1,如果spfa都走完了还没找到,那么返回0

如果用bellman-ford来的话,在松弛n-1次后看有没有d[i]大于s的,有就返回1,否则返回0

/*
bellman_ford
192K 16MS
*/
#include <iostream>
using namespace std;
#define MAXM 410

struct{
	int a,b;
	double rate,com;
}edge[MAXM];

int n,m,s;
double v;

int bellman_ford(){
	int i,j;
	double d[MAXM];
	for(i=0;i<=n;i++) d[i]=0;
	d[s]=v;
	for(i=0;i<n;i++){
		for(j=1;j<=2*m;j++){
			if(d[edge[j].b]<(d[edge[j].a]-edge[j].com)*edge[j].rate){
				d[edge[j].b]=(d[edge[j].a]-edge[j].com)*edge[j].rate;
			}
		}
	}
	for(j=1;j<=2*m;j++){
		if(d[edge[j].b]<(d[edge[j].a]-edge[j].com)*edge[j].rate){
			return 1;
		}
	}
	return 0;
}

int main(){
	int i;
	while(~scanf("%d%d%d%lf",&n,&m,&s,&v)){
		for(i=1;i<=2*m;i+=2){
			scanf("%d%d%lf%lf%lf%lf",&edge[i].a,&edge[i].b,&edge[i].rate,&edge[i].com,&edge[i+1].rate,&edge[i+1].com);
			edge[i+1].a=edge[i].b;
			edge[i+1].b=edge[i].a;
		}
		if(bellman_ford())
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}


=================================================================================

 

/*208K 16MS  */
#include <iostream>
#include <queue>
using namespace std;
#define MAXM 410
#define inf 1e-8

struct{
	int a,b,next;
	double rate,com;
}edge[MAXM];

int n,m,s,headlist[MAXM];
double v;

int spfa(){
	double d[MAXM];
	int i,t,vis[MAXM];
	queue <int>q;
	for(i=1;i<=n;i++){
		d[i]=0;
		vis[i]=0;
	}
	
	q.push(s);
	vis[s]=1;
	d[s]=v;
	while(!q.empty()){
		t=q.front();
		q.pop();
		vis[t]=0;
		
		for(i=headlist[t];i!=-1;i=edge[i].next){
			if(d[edge[i].b]<(d[t]-edge[i].com)*edge[i].rate){
				d[edge[i].b]=(d[t]-edge[i].com)*edge[i].rate;
				if(!vis[edge[i].b]){
					q.push(edge[i].b);
					vis[edge[i].b]=1;
				}
			}
		}
		if(d[s]>v) return 1;
	}
	return 0;
}

int main(){
	int i;
	while(~scanf("%d%d%d%lf",&n,&m,&s,&v)){
		for(i=1;i<=n;i++) headlist[i]=-1;
		for(i=1;i<=2*m;i+=2){
			scanf("%d%d%lf%lf%lf%lf",&edge[i].a,&edge[i].b,&edge[i].rate,&edge[i].com,&edge

[i+1].rate,&edge[i+1].com);
			edge[i+1].a=edge[i].b;
			edge[i+1].b=edge[i].a;

			edge[i].next=headlist[edge[i].a];
			headlist[edge[i].a]=i;

			edge[i+1].next=headlist[edge[i].b];
			headlist[edge[i].b]=i+1;
		}
		if(spfa())
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}


 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值