POJ 1860 Currency Exchange

题目大意:

        现有n种货币以及m种交换方式(1 ≤ n, m ≤ 100),n中货币编号1 ~ n,现给出每种交换方式的汇率以及手续费,形式为"u v r1 c1 r2 c2",其中u、v为两种货币的编号,r1、c1为u兑换到v的汇率以及手续费,而r2、c2为v兑换到u的汇率以及手续费,如果手上有u货币f元,则可兑换到v货币(f - c1)r1元,其中10^-2 ≤ r ≤ 10^2, 0 ≤ c ≤ 10^2,除货币编号外其余都是浮点数。

        现只有一个测例,给出以上信息,以及初始拥有的货币s和货币钱数v,求是否存在一种兑换方式,使得从s开始,兑换一圈回到s后使得到的钱数比起始钱数要大,若存在则输出"YES",否则输出"NO"。

题目链接

注释代码:

/*                           
 * Problem ID : POJ 1860 Currency Exchange
 * Author     : Lirx.t.Una                           
 * Language   : C                
 * Run Time   : 16 ms                           
 * Run Memory : 176 KB                           
*/ 

#include <stdio.h>

//最大货币种数
#define	MAXN	100
//有向图最大边数
#define	MAXM	200

typedef	struct {//有向边
	
	//u->v汇率为r手续费为c
	int		u, v;
	double	r, c; 
} Arc;

Arc		arc[MAXM];//有向边
double	dis[MAXN + 1];//belf的当前最短路径长度
int		e;//边数

void
addarc( int u, int v, double r, double c ) {
	
	arc[e].u = u;
	arc[e].v = v;
	arc[e].r = r;
	arc[e].c = c;
	
	e++;
}

int
belf(int n) {//Bellman-Ford求是否存在能无限松弛的正环
	
	int		cont;
	int		k, i;
	double	tmp;
	
	for ( cont = 1, k = 1; cont && k <= n; k++ )
		for ( cont = 0, i = 0; i < e; i++ )//注意,现在是求最大路径
			if ( ( tmp = ( dis[ arc[i].u ] - arc[i].c ) * arc[i].r ) > dis[ arc[i].v ] ) {
				
				if ( k == n ) return 1;
				
				dis[ arc[i].v ] = tmp;
				cont = 1;
			}
			
			return 0;
}

int
main() {
	
	int		n, m;//n种货币,m种交换方式
	int		s;//起始货币
	double	vv;//起始钱数
	
	int		u, v;
	double	r, c;
	
	int		i;
	
	scanf("%d%d%d%lf", &n, &m, &s, &vv);
	dis[s] = vv;//初始化,自己到自己不经过其它边就是起始钱数
	
	while ( m-- ) {
		
		scanf("%d%d%lf%lf", &u, &v, &r, &c);
		addarc( u, v, r, c );
		scanf("%lf%lf", &r, &c);
		addarc( v, u, r, c );
	}
	
	
	if ( belf(n) ) puts("YES");
	else puts("NO");
	
	return 0;
}
无注释代码:

#include <stdio.h>

#define	MAXN	100
#define	MAXM	200

typedef	struct { 
	
	int		u, v;
	double	r, c; 
} Arc;

Arc		arc[MAXM];
double	dis[MAXN + 1];
int		e;

void
addarc( int u, int v, double r, double c ) {

	arc[e].u = u;
	arc[e].v = v;
	arc[e].r = r;
	arc[e].c = c;

	e++;
}

int
belf(int n) {

	int		cont;
	int		k, i;
	double	tmp;

	for ( cont = 1, k = 1; cont && k <= n; k++ )
		for ( cont = 0, i = 0; i < e; i++ )
			if ( ( tmp = ( dis[ arc[i].u ] - arc[i].c ) * arc[i].r ) > dis[ arc[i].v ] ) {
			
				if ( k == n ) return 1;

				dis[ arc[i].v ] = tmp;
				cont = 1;
			}

	return 0;
}

int
main() {

	int		n, m;
	int		s;
	double	vv;

	int		u, v;
	double	r, c;

	int		i;

	scanf("%d%d%d%lf", &n, &m, &s, &vv);
	dis[s] = vv;

	while ( m-- ) {
	
		scanf("%d%d%lf%lf", &u, &v, &r, &c);
		addarc( u, v, r, c );
		scanf("%lf%lf", &r, &c);
		addarc( v, u, r, c );
	}


	if ( belf(n) ) puts("YES");
	else puts("NO");

	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值