POJ 1860 Bellman-Ford算法
转载链接:http://blog.csdn.net/lyy289065406/article/details/6645778
提示:关键在于反向利用Bellman-Ford算法
题目大意
有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加
货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的
怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)
题目分析:
一种货币就是图上的一个点
一个“兑换点”就是图上两种货币之间的一个兑换环,相当于“兑换方式”M的个数,是双边
唯一值得注意的是权值,当拥有货币A的数量为V时,A到A的权值为K,即没有兑换
而A到B的权值为(V-Cab)*Rab
本题是“求最大路径”,之所以被归类为“求最小路径”是因为本题题恰恰与bellman-Ford算法的松弛条件相反,求的是能无限松弛的最大正权路径,但是依然能够利用bellman-Ford的思想去解题。
因此初始化d(S)=V 而源点到其他店的距离(权值)初始化为无穷小(0),当s到其他某点的距离能不断变大时,说明存在最大路径
附个人代码:(POJ貌似是挂了。。。无限循环CE。。。。宝宝要哭了。。。。T_T)
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int n, m, fn; // 分别表示货币种数 、 转换点 、 源点 、 源点权值
double fv;
double dis[210];
struct Node
{
int u, v;
double r, c; // c 兑换费用 r 兑换率
}edge[210];
int tot = 0; // 边数 n 是点数
bool relax(int j)
{
double t = (dis[edge[j].u] - edge[j].c) * edge[j].r;
if (dis[edge[j].v] < t) // 与bellman 算法刚好相反。bellman算法用来找找负环 求最短路径
{ //这里用同样的思想找正环 求最长路径
dis[edge[j].v] = t;
return true;
}
return false;
}
bool bellman(int ori)
{
memset(dis, 0, sizeof(dis));
dis[ori] = fv;
bool flag;
for (int i=0; i<n; ++i) // 尝试n-1次(对每个点一次) 对每条边进行松弛。寻找最长边
{ // 若不存在负环则可以确定源点到 每个顶点的 最长距离
flag = false;
for (int j=0; j<tot; ++j)
{
if (relax(j)) flag = true;
//if (flag == false) return false;
}
if (dis[ori] > fv) return true;
if (flag == false) return false;
}
for (int i=0; i<tot; ++i)
{
if (relax(i)) return true;
}
return false;
}
int main()
{
while (~scanf("%d%d%d%lf", &n, &m, &fn, &fv))
{
tot = 0;
for (int i=0; i<m; ++i)
{
int a, b;
double rab, cab, rba, cba;
scanf("%d%d%f%f%f%f", &a, &b, &rab, &cab, &rba, &cba);
edge[tot].u = a;
edge[tot].v = b;
edge[tot].r = rab;
edge[tot++].c = cab;
edge[tot].u = b;
edge[tot].v = a;
edge[tot].r = rba;
edge[tot++].c = cba;
}
if (bellman(fn))
printf("YES\n");
else printf("NO\n");
}
return 0;
}
附标准代码:
#include<iostream>
using namespace std;
int n; //货币种数
int m; //兑换点数量
int s; //持有第s种货币
double v; //持有的s货币的本金
int all; //边总数
double dis[101]; //s到各点的权值
class exchange_points
{
public:
int a; //货币a
int b; //货币b
double r; //rate
double c; //手续费
}exc[202];
bool bellman(void)
{
memset(dis,0,sizeof(dis)); //这里与bellman的目的刚好相反。初始化为源点到各点距离无穷小
dis[s]=v; //即bellman本用于找负环,求最小路径,本题是利用同样的思想找正环,求最大路径
/*relax*/
bool flag;
for(int i=1;i<=n-1;i++)
{
flag=false;
for(int j=0;j<all;j++)
if(dis[exc[j].b] < (dis[exc[j].a] - exc[j].c) * exc[j].r) //寻找最长路径
{ //进行比较的是"某点到自身的权值"和"某点到另一点的权值"
dis[exc[j].b] = (dis[exc[j].a] - exc[j].c) * exc[j].r;
flag=true;
}
if(!flag)
break;
}
/*Search Positive Circle*/
for(int k=0;k<all;k++)
if(dis[exc[k].b] < (dis[exc[k].a] - exc[k].c) * exc[k].r) //正环能够无限松弛
return true;
return false;
}
int main(void)
{
int a,b;
double rab,cab,rba,cba; //临时变量
while(cin>>n>>m>>s>>v)
{
all=0; //注意初始化
for(int i=0;i<m;i++)
{
cin>>a>>b>>rab>>cab>>rba>>cba;
exc[all].a=a;
exc[all].b=b;
exc[all].r=rab;
exc[all++].c=cab;
exc[all].a=b;
exc[all].b=a;
exc[all].r=rba;
exc[all++].c=cba;
}
/*Bellman-form Algorithm*/
if(bellman())
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
POJ 1860 Bellman-Ford算法的更多相关文章
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】
题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...
- poj 1860 bellman 求正环
#include<stdio.h> #include<string.h> #include<queue>//只需判断是否有正环路径就可以了 using namesp ...
- poj1860 bellman—ford队列优化 Currency Exchange
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22123 Accepted: 799 ...
- POJ 1860 Currency Exchange (最短路)
Currency Exchange Time Limit : 2000/1000ms (Java/Other) Memory Limit : 60000/30000K (Java/Other) T ...
- uva 558 - Wormholes(Bellman Ford判断负环)
题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...
- POJ 3259 Wormholes SPFA算法题解
版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...
- poj 1860 Currency Exchange (SPFA、正权回路 bellman-ford)
链接:poj 1860 题意:给定n中货币.以及它们之间的税率.A货币转化为B货币的公式为 B=(V-Cab)*Rab,当中V为A的货币量, 求货币S通过若干此转换,再转换为原本的货币时是否会添加 分 ...
- POJ 1860 Currency Exchange (Bellman-Ford)
题目链接:POJ 1860 Description Several currency exchange points are working in our city. Let us suppose t ...
随机推荐
- tf.equal的使用
tf.equal(A, B)是对比这两个矩阵或者向量的相等的元素,如果是相等的那就返回True,反正返回False,返回的值的矩阵维度和A是一样的 import tensorflow as tf im ...
- 【基础配置】Dubbo的配置及使用
1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...
- [Err] 1111 - Invalid use of group function
本文为博主原创,未经允许不得转载: 初衷,本想通过group by sql语句查询出不同id下总数在一定范围内的数据,所以产生如下的sql,及错误sql AND STATDATE < ' GRO ...
- codeforces 251 div2 D. Devu and his Brother 三分
D. Devu and his Brother time limit per test 1 second memory limit per test 256 megabytes input stand ...
- Ubuntu14.04 libboost_program_options.so.1.54.0: cannot open shared object file: No such file or directory
macname@ubuntu:~/Desktop$ roslaunch blackrospack: error : cannot open shared object file: No such fi ...
- html 画出矩形,鼠标弹起,矩形消失
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- Qt5.3.2_CentOS6.4_基本编程环境__20160306【勿删,繁琐】
20160306 全程没有f/q ZC:使用的虚拟机环境是:博客园VMwareSkill 的 “CentOS6.4_x86_120g__20160306.rar” 1. 执行命令“gcc -v”,显示 ...
- Qt5_pro_01
1. QT += core gui \ sql \ #ZC: 这个对应 #include <SQL/???> (如<QtSql/QSqlDatabase><QtSql/Q ...
- c语言的左移和右移
转自:https://www.cnblogs.com/myblesh/articles/2431806.html 先说左移,左移就是把一个数的所有位都向左移动若干位,在C中用<<运算符.例 ...
- 《剑指offer》第十三题(机器人的运动范围)
// 面试题:机器人的运动范围 // 题目:地上有一个m行n列的方格.一个机器人从坐标(0, 0)的格子开始移动,它 // 每一次可以向左.右.上.下移动一格,但不能进入行坐标和列坐标的数位之和 // ...