POJ 1860 题解与Bellman-Ford 贝尔曼-福特算法的实现

题目地址

这是地址

AC代码

#include <iostream>

using namespace std;

int main() {
    int n,t,have;
    double money;
    cin>>n>>t>>have>>money;
    int s[2*t],v[2*t];
    double c[2*t],r[2*t],dis[n+1];
    for (int i = 0; i < 2*t; i+=2) {
        int huobi1,huobi2;
        cin>>huobi1>>huobi2;
        double rab,cab,rba,cba;
        cin>>rab>>cab>>rba>>cba;
        s[i]=huobi1,v[i]=huobi2,r[i]=rab,c[i]=cab;
        s[i+1]=huobi2,v[i+1]=huobi1,r[i+1]=rba,c[i+1]=cba;
    }
    for (int j = 1; j <=t ; ++j) {
        dis[j]=0;
    }
    dis[have]=money;
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < 2*t; ++i) {
            if(dis[v[i]]<(dis[s[i]]-c[i])*r[i])dis[v[i]]=(dis[s[i]]-c[i])*r[i];
        }
    }
    int boo = 0;
    for (int k = 0; k < n; ++k) {
        for (int i = 0; i < 2*t; ++i) {
            if(dis[v[i]]<(dis[s[i]]-c[i])*r[i]){
                boo = 1;
                break;
            }
        }
    }
    if(boo)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

题解和题目思路

这题使用的是更改过后的Bellman-Ford算法,将原有的查找最短路径以及负权值回环转化为了查找最长路径及正权值回环。
Bellman-Ford算法的实现可以看下面,这里先讲题目的思路。
本题的dis[]数组存放的是由一开始持有的货币在经过k次松弛之后得到的当前种类货币的金额。
按照惯例,在松弛完n-1次之后,如果还存在可以松弛的情况,那么我们就可以判断这里存在回环。本题就意味着一定存在正回环,可以使得货币越换越多,钱生钱 //滑稽
如果存在回环,则输出YES,否则就输出NO

原始的Bellman-Ford算法实现

#include <iostream>

using namespace std;

int main() {
    int t,n,b,e;
    cin>>t>>n>>b>>e;	//初始化点的数目,边的数目,起点和终点编号
    int s[n],v[n],w[n],dis[t+1];
    for (int i = 0; i < n; ++i) {
        cin>>s[i]>>v[i]>>w[i];	//输入边的信息,如果是无向图请自行添加多余的边
    }
    for (int k = 0; k <= t; ++k) {	//初始化距离数组
        dis[k]=6666;
    }
    dis[b]=0;
    for (int j = 0; j < t; ++j) {	//进行松弛,查找最短路径
        for (int i = 0; i < n; ++i) {
            if(dis[v[i]]>dis[s[i]]+w[i])dis[v[i]]=dis[s[i]]+w[i];
        }
    }
    int boo = 0;
    for (int j = 0; j < t; ++j) {	//判断是否存在负权回环
        for (int i = 0; i < n; ++i) {
            if(dis[v[i]]>dis[s[i]]+w[i]){
                boo = 1;
                break;
            }
        }
    }
    if(boo)cout<<"不存在最短路径";
    else cout<<dis[e];
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值