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 ...
随机推荐
- Mac标识物理位置算法 import Levenshtein mac列表特征值
mac 字符串 与 基准字符串的 Levenshtein 距离,考虑 mac信号强度的时序性,60秒内若干次变化 不引入强度 mac字符串的唯一性 如何排序 基准字符串的选取 同一尺度 都按强度 ...
- LeetCode:柠檬水找零【860】
LeetCode:柠檬水找零[860] 题目描述 在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向 ...
- 用cocos2d-html5做的消除类游戏《英雄爱消除》(3)——游戏主界面
游戏主界面,同时也是主程序,包括sprite的生成加入以及游戏状态的控制. 下面同样贴下源码再讲解; /** * Power by html5中文网(html5china.com) * author: ...
- Redis缓存全自动安装shell脚本
我只是把命令放到shell文件中了,方便安装,代码如下: #!/bin/bash # shell的执行选项: # -n 只读取shell脚本,但不实际执行 # -x 进入跟踪方式,显示所执行的每一条命 ...
- Android 双u盘方案【转】
本文转载自:https://blog.csdn.net/kc58236582/article/details/49618445 1 L1813系统上双U盘设计方案——系统设计 1.1 ...
- Quota Management and Enforcement
Neutron API中大多的resource都需要quota limits. Neutron API暴露出一个extension 来管理quota,Quota limits are enforced ...
- jQuery创建DOM的方法
jQuery1.4带来了一个全新的便捷地清晰的DOM对象创建方法,在 jQuery 1.4中,我们可以传递一个对象作为第二个参数. 这个参数接受一个属性的集合,这些可以传递给.attr() 方法.此外 ...
- HTML-CSS浮动元素详解
浮动定位是指 1.1将元素排除在普通流之外,即元素将脱离标准文档流 1.2元素将不在页面占用空间 1.3将浮动元素放置在包含框的左边或者右边 1.4浮动元素依旧位于包含框之内 2. 浮动的框可以向左或 ...
- 英语发音规则---oo
英语发音规则---oo 一.总结 一句话总结: 1.重读音节词尾的字母组合oo发音素[u:]的音? too [tu:] adv.太;也 zoo [zu:] n.动物园 room [ru:m] n.房间 ...
- Java企业微信开发_08_素材管理之下载微信临时素材到本地服务器
一.本节要点 1.获取临时素材接口 请求方式:GET(HTTPS) 请求地址:https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=AC ...