转载链接: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算法的更多相关文章

  1. Bellman—Ford算法思想

    ---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...

  2. Bellman - Ford 算法解决最短路径问题

    Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...

  3. Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】

    题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...

  4. poj 1860 bellman 求正环

    #include<stdio.h> #include<string.h> #include<queue>//只需判断是否有正环路径就可以了 using namesp ...

  5. poj1860 bellman—ford队列优化 Currency Exchange

    Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22123   Accepted: 799 ...

  6. POJ 1860 Currency Exchange (最短路)

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

  7. uva 558 - Wormholes(Bellman Ford判断负环)

    题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...

  8. POJ 3259 Wormholes SPFA算法题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...

  9. poj 1860 Currency Exchange (SPFA、正权回路 bellman-ford)

    链接:poj 1860 题意:给定n中货币.以及它们之间的税率.A货币转化为B货币的公式为 B=(V-Cab)*Rab,当中V为A的货币量, 求货币S通过若干此转换,再转换为原本的货币时是否会添加 分 ...

  10. POJ 1860 Currency Exchange (Bellman-Ford)

    题目链接:POJ 1860 Description Several currency exchange points are working in our city. Let us suppose t ...

随机推荐

  1. 【javascript】数据结构-链表

    // 创建一个链表 function LinkedList(){ // 创建一个Node辅助类,表示需要加入列表的项,它包含一个element属性,即表示需要加入到列表中的值,next属性表示指向下一 ...

  2. hdu Naive Operations 线段树

    题目大意 题目链接Naive Operations 题目大意: 区间加1(在a数组中) 区间求ai/bi的和 ai初值全部为0,bi给出,且为n的排列,多组数据(<=5),n,q<=1e5 ...

  3. MOOC_Java进阶_翁恺讲_第三周题

    package mooc_java进阶_d3周题; /** * 没有使用HashMap */ import java.util.ArrayList; import java.util.Scanner; ...

  4. java反射基础

    转载请注明出处:https://i.cnblogs.com/EditPosts.aspx?opt=1最近在接触到框架的底层的时候,遇到了反射,便想好好的学习和总结一下反射,帮助理解java框架的运行流 ...

  5. 非[无]root权限 服务器 下安装perl以及perl模块

    转载自http://www.zilhua.com 在本博客中,所有的软件安装都在服务器上,且无root权限.理论上适合所有的用户. 我的安装目录 cd /home/zilhua/software 1. ...

  6. ros pbstream

    https://blog.csdn.net/xiekaikaibing/article/details/80320822

  7. JavaScript权威指南--脚本化CSS

    知识要点 客户端javascript程序员对CSS感兴趣的是因为样式可以通过脚本编程.脚本化css启用了一系列有趣的视觉效果.例如:可以创建动画让文档从右侧“滑入”.创造这些效果的javascript ...

  8. union和union all比较说明

    执行sql语句:select '1' union select '3' union select '2'  union select '1' 得到的结果集如下: 执行sql语句如下: select ' ...

  9. 为什么需要API网关?

    目录 0:00 微服务与网关(Microservices & API Gateways) 大家好,我叫Macro,今天我们谈论有关微服务和网关的话题.我是Mashape的CTO,也同时是开源网 ...

  10. 雷林鹏分享:Ruby 字符串(String)

    Ruby 字符串(String) Ruby 中的 String 对象存储并操作一个或多个字节的任意序列,通常表示那些代表人类语言的字符. 最简单的字符串是括在单引号(单引号字符)内.在引号标记内的文本 ...