POJ - 1860 (Currency Exchange)

题意:给定若干种货币之间兑换的汇率和手续费,初始给定一种货币和价值,问能不能通过一系列兑换最后回到初始货币种类时价值上升

 

分析:每种货币代表一个点,给货币兑换的关系看作两点的边建图,跑一遍SPFA判正环,若存在正环则必有解使得最终货币价值上升,为什么,因为按照正环兑换一遍价值就会上升,那么一定可以通过有限次正环使得价值大到回到起点的时候价值依然大于初始值;

 

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int N = 100+10;
const int INF = 0X3F3F3F3F3F;
struct node{
	int to,nxt;
	double rate,com;
	node(){}
	node(int _to,int _nxt,double _rate,double _com):to(_to),nxt(_nxt),rate(_rate),com(_com){}
}e[N<<1];
int head[N],tot;

void add(int u,int v,double r,double c){
	e[tot]=node(v,head[u],r,c);
	head[u]=tot++;
}

int n,m,vis[N],out[N],S;
double dis[N],w;

bool SPFA(){
	for(int i=1;i<=n;i++) dis[i]=-INF,vis[i]=out[i]=0;
	vis[S]=1,out[S]=1,dis[S]=w; 
	queue<int>que;
	que.push(S);
	while(!que.empty()){
		int u=que.front(); que.pop(); vis[u]=0;
		for(int i=head[u];i!=-1;i=e[i].nxt){
			int v=e[i].to;
		    double r=e[i].rate,c=e[i].com;
		    if(dis[v]<(dis[u]-c)*r){
		    	dis[v]=(dis[u]-c)*r;
		    	if(!vis[v]){
		    		vis[v]=1;
		    		que.push(v);
		    		if(++out[v]>n) return true;
				}
			}
			if(dis[S]>w) return true;
		}
	}
	return false;
} 

int main()
{
	memset(head,-1,sizeof(head)),tot=0;
	scanf("%d%d%d%lf",&n,&m,&S,&w);
	for(int i=0;i<m;i++){
		int u,v;
		double r1,c1,r2,c2;
		scanf("%d%d%lf%lf%lf%lf",&u,&v,&r1,&c1,&r2,&c2);
		add(u,v,r1,c1);
		add(v,u,r2,c2);
	}
	if(SPFA()) printf("YES");
	else printf("NO"); 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值