Poj 1860 Currency Exchange(Bellman-Ford,SPFA解单源最短路径问题)
一、题意
有多个货币交易点,每个只能互换两种货币,兑换的汇率不同,并收取相应的手续费。有N种货币,假定你拥有第S中,数量为V,有M个兑换点。问你能不能通过兑换操作使你最后拥有的S币比起始的时候多。
二、题解
货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路(在这一回路上,顶点的权值能不断增加,即能一直进行松弛),且最后得到的s金额是增加的。说到松弛我们立即会想到Bellman-Ford算法,它的特点是可以处理负权边,并能判断是否存在负环(负权回路)。本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。关于bellman-Ford算法请关注本博客对它的详细分析。
bellman-Ford算法的时效性较好,时间复杂度O(VE)。这里也介绍一下它的队列优化算法SPFA。它是Bellman-Ford的队列优化,时效性相对好,时间复杂度O(kE)。(k<<V)。与Bellman-ford算法类似,SPFA算法采用一系列的松弛操作以得到从某一个节点出发到达图中其它所有节点的最短路径。所不同的是,SPFA算法通过维护一个队列,使得一个节点的当前最短路径被更新之后没有必要立刻去更新其他的节点,从而大大减少了重复的操作次数。
三、java算法
bellman-Ford算法
import java.util.Scanner;
class Edge{
int startNode,endNode;
double exchangeRate;
double commission;
}
public class Main{ static Edge[] edge=new Edge[210];
static int pe;
static int N,M,S;
static double V;
static double dis[]=new double[110]; static boolean bellman_ford(){
boolean sign = false;
dis[S]=V;
for(int j=0;j<N+1;j++){
sign=false;
for(int i=0;i<pe;i++)
if(dis[edge[i].endNode]<(dis[edge[i].startNode]-edge[i].commission)*edge[i].exchangeRate){
dis[edge[i].endNode]=(dis[edge[i].startNode]-edge[i].commission)*edge[i].exchangeRate;
sign=true;
}
if(!sign)
break;
}
if(sign)
return false;
else
return true;
} public static void main(String args[]){
Scanner sc=new Scanner(System.in);
for(int i=0;i<210;i++){
edge[i]=new Edge();
}
N=sc.nextInt();
M=sc.nextInt();
S=sc.nextInt();
V=sc.nextDouble();
pe=0;
int a,b;
double rab,cab,rba,cba; for(int i=0;i<M;i++){
a=sc.nextInt();
b=sc.nextInt();
rab=sc.nextDouble();
cab=sc.nextDouble();
rba=sc.nextDouble();
cba=sc.nextDouble();
edge[pe].startNode=a;
edge[pe].endNode=b;
edge[pe].exchangeRate=rab;
edge[pe++].commission=cab;
edge[pe].startNode=b;
edge[pe].endNode=a;
edge[pe].exchangeRate=rba;
edge[pe++].commission=cba;
}
if(bellman_ford())
System.out.println("NO");
else
System.out.println("YES");
}
}
SFPA算法
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main{ static int MAX_Node =110;
static int N,M,S;
static double V;
static double exchangeRate[][]=new double[MAX_Node][MAX_Node];
static double commission[][]=new double[MAX_Node][MAX_Node]; public static boolean spfa(int start){
Queue<Integer> Que=new LinkedList<Integer>();
int cnt[]=new int[MAX_Node]; //记录进入队列的次数,超过N则存在正权回路
boolean[] vst=new boolean[MAX_Node]; //记录节点是否在队列中、
double[] dis=new double[MAX_Node]; //记录每个结点的最短路径估计值
for(int i=0;i<=N;i++){
vst[i]=false;
cnt[i]=0;
dis[i]=0;
}
dis[start]=V;
vst[start]=true;
cnt[start]=1;
Que.add(start);
while(Que.size()!=0){
int u=Que.poll();
vst[u]=false;
for(int i=1;i<=N;i++){
if(exchangeRate[u][i]>0 && ((dis[u]-commission[u][i]) * exchangeRate[u][i]) > dis[i]){
dis[i]=(dis[u]-commission[u][i]) * exchangeRate[u][i]; //松弛
if(!vst[i]){
vst[i]=true;
Que.add(i);
cnt[i]++;
if(cnt[i]>=N)
return true;
}
}
}
}
return dis[S]>V;
} public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int i;
N=sc.nextInt();
M=sc.nextInt();
S=sc.nextInt();
V=sc.nextDouble();
for(i=0;i<M;i++){
int a,b;
a=sc.nextInt();
b=sc.nextInt();
exchangeRate[a][b]=sc.nextDouble();
commission[a][b]=sc.nextDouble();
exchangeRate[b][a]=sc.nextDouble();
commission[b][a]=sc.nextDouble();
}
if(spfa(S))
System.out.println("YES");
else
System.out.println("NO");
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
Poj 1860 Currency Exchange(Bellman-Ford,SPFA解单源最短路径问题)的更多相关文章
- POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环)
POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环) Description Several currency ...
- 最短路(Bellman_Ford) POJ 1860 Currency Exchange
题目传送门 /* 最短路(Bellman_Ford):求负环的思路,但是反过来用,即找正环 详细解释:http://blog.csdn.net/lyy289065406/article/details ...
- POJ 1860 Currency Exchange (最短路)
Currency Exchange Time Limit : 2000/1000ms (Java/Other) Memory Limit : 60000/30000K (Java/Other) T ...
- POJ 1860 Currency Exchange 最短路+负环
原题链接:http://poj.org/problem?id=1860 Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Tota ...
- POJ 1860 Currency Exchange + 2240 Arbitrage + 3259 Wormholes 解题报告
三道题都是考察最短路算法的判环.其中1860和2240判断正环,3259判断负环. 难度都不大,可以使用Bellman-ford算法,或者SPFA算法.也有用弗洛伊德算法的,笔者还不会SF-_-…… ...
- SPFA解决单源最短路径
SPFA(Shortest Path Faster Algorithm): 一:基本算法 在求解单源最短路径的时候,最经典的是 Dijkstra 算法,但是这个算法对于含有负权的图就无能为力了,而 B ...
- SPFA求单源最短路径
序 求最短路径的算法有很多,各有优劣. 比如Dijkstra(及其堆(STL-priority_queue)优化),但是无法处理负环的情况: 比如O(n^3)的Floyd算法:比如Bellman-Fo ...
- POJ 1860——Currency Exchange——————【最短路、SPFA判正环】
Currency Exchange Time Limit:1000MS Memory Limit:30000KB 64bit IO Format:%I64d & %I64u S ...
- 图论 --- spfa + 链式向前星 : 判断是否存在正权回路 poj 1860 : Currency Exchange
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 19881 Accepted: 711 ...
随机推荐
- recognition rate generalization识别率 泛化
http://www1.inf.tu-dresden.de/~ds24/lehre/ml_ws_2013/ml_11_hinge.pdf Two extremes: • Big
- springboot + swagger2 学习笔记
引入步骤 1.添加依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springf ...
- [note]树链剖分
树链剖分https://www.luogu.org/problemnew/show/P3384 概念 树链剖分,是一种将树剖分成多条不相交的链的算法,并通过其他的数据结构来维护这些链上的信息. 最简单 ...
- python+NLTK 自然语言学习处理五:词典资源
前面介绍了很多NLTK中携带的词典资源,这些词典资源对于我们处理文本是有大的作用的,比如实现这样一个功能,寻找由egivronl几个字母组成的单词.且组成的单词每个字母的次数不得超过egivronl中 ...
- Java的接口和抽象类(转发:http://www.importnew.com/18780.html)
深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...
- LeetCode:最少移动次数使得数组元素相等||【462】
LeetCode:最少移动次数使得数组元素相等||[462] 题目描述 给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1. 您可以假设数组的长度最 ...
- cookie补充
之前写cookie中关于突破同源策略共享cookie说的比较含糊,此次来详细说明一下: ## 首先说一下cookie的path和domain这 两个属性值 path: path表示的此条cookie是 ...
- vo类总结
1.Camera类 camera类里面,首先camera有5个变量,fx_,fy_,cx_,cy_,depth_scale_5个变量,由外部传fx,fy,cx,cy,depth_scale给它.定义了 ...
- vim配置与使用
Vim 是一个上古神器,本篇文章主要持续总结使用 Vim 的过程中不得不了解的一些指令和注意事项,以及持续分享一个前端工作者不得不安装的一些插件,而关于 Vim 的简介,主题的选择,以及为何使用 vi ...
- 随意谈谈tcp
tcp作为四层中可靠到传输协议,为上层协议提供了字节流的可靠到传输,之所以能做到可靠主要因为以下几点: 1.流与分段:流即字节流,计算机处理程序时一般以字节为单位,如果上层协议接收到到是字节流并且跟发 ...