一、题意

有多个货币交易点,每个只能互换两种货币,兑换的汇率不同,并收取相应的手续费。有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解单源最短路径问题)的更多相关文章

  1. POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环)

    POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环) Description Several currency ...

  2. 最短路(Bellman_Ford) POJ 1860 Currency Exchange

    题目传送门 /* 最短路(Bellman_Ford):求负环的思路,但是反过来用,即找正环 详细解释:http://blog.csdn.net/lyy289065406/article/details ...

  3. POJ 1860 Currency Exchange (最短路)

    Currency Exchange Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 60000/30000K (Java/Other) T ...

  4. POJ 1860 Currency Exchange 最短路+负环

    原题链接:http://poj.org/problem?id=1860 Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Tota ...

  5. POJ 1860 Currency Exchange + 2240 Arbitrage + 3259 Wormholes 解题报告

    三道题都是考察最短路算法的判环.其中1860和2240判断正环,3259判断负环. 难度都不大,可以使用Bellman-ford算法,或者SPFA算法.也有用弗洛伊德算法的,笔者还不会SF-_-…… ...

  6. SPFA解决单源最短路径

    SPFA(Shortest Path Faster Algorithm): 一:基本算法 在求解单源最短路径的时候,最经典的是 Dijkstra 算法,但是这个算法对于含有负权的图就无能为力了,而 B ...

  7. SPFA求单源最短路径

    序 求最短路径的算法有很多,各有优劣. 比如Dijkstra(及其堆(STL-priority_queue)优化),但是无法处理负环的情况: 比如O(n^3)的Floyd算法:比如Bellman-Fo ...

  8. POJ 1860——Currency Exchange——————【最短路、SPFA判正环】

    Currency Exchange Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u S ...

  9. 图论 --- spfa + 链式向前星 : 判断是否存在正权回路 poj 1860 : Currency Exchange

    Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 19881   Accepted: 711 ...

随机推荐

  1. 使用weka训练一个分类器

    1 训练集数据 1.1 csv格式 5.1,3.5,1.4,0.2,Iris-setosa 4.9,3.0,1.4,0.2,Iris-setosa 4.7,3.2,1.3,0.2,Iris-setos ...

  2. springboot工程自动生成工具

    1 springboot工程自动生成网址 http://start.spring.io/ 2 工具 Spring Boot CLI

  3. 20179209《Linux内核原理与分析》安全类实验答疑

    实验一 题目 Nmap 配合 Metasploit 进行端口扫描 问题 Nmap怎么配合Metasploit进行端口扫描? 回答 这里的Nmap配合Metasploit进行端口扫描是指在Metaspl ...

  4. java基础入门1到100的奇数求和

    /* Name:1-100所有奇数求和的程序 Power by Stuart Date:2015-4-23 */ public class DateTest01{ public static void ...

  5. iOS 8以后 定位手动授权问题

    ios8以后 都是手动授权定位权限 不过不处理这块 在ios8以后的系统就会默认永不授权 即关闭了定位权限 处理办法如下 .导入框架头文件 #import <CoreLocation/CoreL ...

  6. Java编程思想(第4版) 中文清晰PDF完整版

    Java编程思想(第4版) 中文清晰PDF完整版 [日期:2014-08-11] 来源:Linux社区  作者:Linux [字体:大 中 小]     <Java编程思想>这本书赢得了全 ...

  7. Data Structure Binary Tree: Construct Tree from given Inorder and Preorder traversals

    http://www.geeksforgeeks.org/construct-tree-from-given-inorder-and-preorder-traversal/ #include < ...

  8. 左侧图片 右侧块的实现方法---解决3像素bug的一种解决方案,不用浮动用绝对定位和margin-left

    google的实现方式是: <div class="mw"> <a href="/" id="mlogo">  &l ...

  9. <再看TCP/IP第一卷>TCP/IP协议族中的最压轴戏----TCP协议及细节

    题外话:刚刚过去的半个月实在是忙得我喘不过来气,虽然手里还压着几个项目得在期末考试之前做完,但是想想还是更新一下随笔,稍微换个心情.另外小吐槽一下那些在博客园里原封不动抄书当随笔的人,唉真是....算 ...

  10. NOIP前的一些计划

    一些想法 距离NOIP2018只剩下一个星期的时间了,通过这几天在长郡的考试,渐渐感觉还有好多东西自己还不够熟练,也有些东西到现在还不会,现将NOIP前的一些计划列在这里,希望能在考前把他们全部完成吧 ...