题意:

给出一些货币和货币之间的兑换比率,问是否可以使某种货币经过一些列兑换之后,货币值增加。

举例说就是1美元经过一些兑换之后,超过1美元。可以输出Yes,否则输出No。

分析:

首先我们要把货币之间的关系转化成一张图。转化时,用STL里面的map很方便。

为每种货币分配一个序列号,一个序列号代表了一个图中间的NODE,而node之间的edge用汇率表示。

一开始用Dijkstra算法做,死活AC不了,网友给的理由是:

由于Dijkstra算法不能处理带有负权值的最短路,但此题中,两种货币之间的兑换比率可能小于1,相当于这条路径的权值为负

前车之鉴,WA的代码:

#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<string>
#include<map>
using namespace std;
#define maxn 31
#define inf 0x3f3f3f3f
double edges[maxn][maxn];
double dist[maxn];
typedef pair<int,int> P;
void init(){
for(int i=1;i<maxn;i++)
for(int j=1;j<maxn;j++)
edges[i][j]=(i==j?1:0);//1代表等价价换,0:代表无法交换
} void dijkstra(int s,int n){
bool visited[maxn];
memset(visited,0,sizeof(visited));
visited[s]=true;
for(int i=1;i<=n;i++)
dist[i]=edges[s][i];
for(int i=1,u;i<=n;i++){
double max=-1;
for(int j=1;j<=n;j++)
if(!visited[j]&&dist[j]>max){
max=dist[j]; u=j;
} visited[u]=true;
for(int j=1;j<=n;j++){
if(dist[u]*edges[u][j]>dist[j])
dist[j]=dist[u]*edges[u][j];
}
}
} int main(){
//freopen("in.txt","r",stdin);
int n,cases=0;
while(scanf("%d",&n)!=EOF && n){
cases++;
init();
map<string,int> ma;
string s,t;
for(int i=1;i<=n;i++){
cin>>s;
ma.insert(make_pair(s,i));
}
int m;
double tmp;
scanf("%d",&m);
while(m--){
cin>>s>>tmp>>t;
edges[ma[s]][ma[t]]=tmp;
} dijkstra(1,n);
printf("Case %d: ",cases);
if(dist[1]>1.0)
printf("Yes\n");
else
printf("No\n");
}
}

最后写了一个Floyd的代码版本,结果一下子就过了,我只能默默的哭了

#include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<string>
#include<map>
using namespace std;
#define maxn 31
#define inf 0x3f3f3f3f
double edges[maxn][maxn];
void init(){
for(int i=1;i<maxn;i++)
for(int j=1;j<maxn;j++)
edges[i][j]=(i==j?1:0);//1:代表等价交换,0:代表无法交换
} void floyd_warshall(int s,int n){
for(int k=1;k<=n;k++){
for(int i=1,u;i<=n;i++){
for(int j=1;j<=n;j++){
if(edges[i][k]*edges[k][j]>edges[i][j])//如果找到了更好的交换方案
edges[i][j]=edges[i][k]*edges[k][j];
}
}
}
} int main(){
//freopen("in.txt","r",stdin);
int n,cases=0;
while(scanf("%d",&n)!=EOF && n){
cases++;
init();
map<string,int> ma;
string s,t;
for(int i=1;i<=n;i++){
cin>>s;
ma.insert(make_pair(s,i));
}
int m;
double tmp;
scanf("%d",&m);
while(m--){
cin>>s>>tmp>>t;
edges[ma[s]][ma[t]]=tmp;
} dijkstra(1,n);
printf("Case %d: ",cases);
/*for(int i=1,u;i<=n;i++){
for(int j=1;j<=n;j++){
printf("%.2f ",edges[i][j]);
}
printf("\n");
}*/
if(edges[1][1]>1.0)
printf("Yes\n");
else
printf("No\n");
}
}

最后再用bellman_ford模板成功ac了一次。

 #include<iostream>
#include<cstdio>
#include<queue>
#include<string.h>
#include<string>
#include<map>
using namespace std; #define maxn 1000
#define inf 0x3f3f3f3f
struct edge{
int from;
int to;
float cost;
edge(){
from=0,to=0,cost=0;
}
edge(int a,int b ,float c){
from=a,to=b,cost=c;
}
};
edge Edges[maxn];
float dist[maxn];
void bellman_ford(int s,int V,int E){
for(int i=1;i<=V;i++)
dist[i]=0;
dist[s]=1.0;
for(int i=1;i<=V;i++){//这里可以改成while(true),但在有负权的情况下,会增加更多的循环,故建议照样例中写
bool update=false;
for(int j=1;j<=E;j++){
edge e=Edges[j];
if(dist[e.to]<dist[e.from]*e.cost){
dist[e.to]=dist[e.from]*e.cost;
update=true;
}
}
if(!update)break;//一旦在某次循环中,不能再更新当前dist,那么就能提前结束该算法,break之
}
} void init(int n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j) Edges[i]=edge(i,j,1.0);//初始化,1:等价交换
else Edges[i]=edge(i,j,0); //0:无法交换
}
}
} int main(){
//freopen("in.txt","r",stdin);
int n,cases=0;
while(scanf("%d",&n)!=EOF && n){
cases++;
init(n);
map<string,int> ma;
string s,t;
for(int i=1;i<=n;i++){
cin>>s;
ma.insert(make_pair(s,i)); //构造字符串与数值的映射关系
}
int m;
double tmp;
scanf("%d",&m);
for(int i=1;i<=m;i++){
cin>>s>>tmp>>t;
Edges[i]=edge(ma[s],ma[t],tmp);
} bellman_ford(1,n,m);
printf("Case %d: ",cases);
if(dist[1]>1.0)
printf("Yes\n");
else
printf("No\n");
}
}

【问题】:Folyd算法能处理包含负权边的图吗?

答案是可以的。Floyd-Warshall算法和Bellman-Ford算法一样,可以处理边是负数的情况。

---《挑战程序设计竞赛》 P.103

POJ 2240 - Arbitrage(bellman_ford & floyd)的更多相关文章

  1. poj 2240 Arbitrage(Bellman_ford变形)

    题目链接:http://poj.org/problem?id=2240 题目就是要通过还钱涨自己的本钱最后还能换回到自己原来的钱种. 就是判一下有没有负环那么就直接用bellman_ford来判断有没 ...

  2. POJ 2240 Arbitrage(Floyed-Warshall算法)

    题意:给出n种货币,m种兑换比率(一种货币兑换为另一种货币的比率),判断测试用例中套汇是否可行.(套汇的意思就是在经过一系列的货币兑换之后,是否可以获利.例如:货币i→货币j→货币i,这样兑换后,是否 ...

  3. POJ 2240 Arbitrage(SPFA+邻接矩阵)

    ( ̄▽ ̄)" #include<iostream> #include<cstdio> #include<cmath> #include<algori ...

  4. poj 2240 Arbitrage (Floyd)

    链接:poj 2240 题意:首先给出N中货币,然后给出了这N种货币之间的兑换的兑换率. 如 USDollar 0.5 BritishPound 表示 :1 USDollar兑换成0.5 Britis ...

  5. POJ 3259 Wormholes (Bellman_ford算法)

    题目链接:http://poj.org/problem?id=3259 Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submis ...

  6. POJ 2240 Arbitrage(floyd)

    http://poj.org/problem?id=2240 题意 : 好吧,又是一个换钱的题:套利是利用货币汇率的差异进行的货币转换,例如用1美元购买0.5英镑,1英镑可以购买10法郎,一法郎可以购 ...

  7. POJ 2240 Arbitrage(判正环)

    http://poj.org/problem?id=2240 题意:货币兑换,判断最否是否能获利. 思路:又是货币兑换题,Belloman-ford和floyd算法都可以的. #include< ...

  8. POJ 2240 Arbitrage (求负环)

    Arbitrage 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/I Description Arbitrage is the ...

  9. POJ 2240 Arbitrage (Bellman Ford判正环)

    Arbitrage Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:27167   Accepted: 11440 Descri ...

随机推荐

  1. 从源码角度看finish()方法的执行流程

    1. finish()方法概览 首先我们来看一下finish方法的无参版本的定义: /** * Call this when your activity is done and should be c ...

  2. EF增删改查操作

    增 using (StudentEntities ent = new StudentEntities()) { User aNewUser = new User() { Age = , Name = ...

  3. [bzoj2286][Sdoi2011]消耗战(虚树上的DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2286 分析:对于普通的树形dp:f[x]=min(∑f[son],m[x]),其中f[ ...

  4. why does turn off button means hibernate on my win8

    when I upgrated my laptop's system to win8.*,I found it's hibernate when I clicked turn off button. ...

  5. C#分割字符串

    命名空间:System.String.Split 程序集:mscorlib( mscorlib.dll) 简单实例: string before = "12,50,30"; str ...

  6. PHP中生成json信息的方法

    <?php //php中生成json信息 //json_encode(数组/对象) $color = array('red','blue','green'); //[索引数组] echo jso ...

  7. GDB的使用

    #list #break <行号|函数名|条件表达式> #delete  #run #continue #finish #quit #next #step #print #watch  l ...

  8. (function($, window, document) {}) jQuery 调用解决与其他javascript库冲突的写法

    将函数包在红色字体内部,可以解决$符号与其他插件的冲突. <script type="text/javascript"> (function($, window, do ...

  9. 函数也是对象,本片介绍函数的属性、方法、Function()狗仔函数。

    1.arguments.length表示实参的个数. 2.arguments.callee.length表示形参个数. function test(a,b,c,d,e,f){ alert(argume ...

  10. iOS开发小技巧--定时器的使用技巧

    一.定时器的使用技巧 -- 定义好了定时器后,添加两个方法,一个是添加定时器的方法,另一个是移除定时器的方法. 使用的时候也要注意,一定先移除之前的timer,然后再添加timer