poj 1860 Bellman-Ford

这道题是Bellman-Ford求最长路径的应用。

这里给一个Bellman-Ford求最短路径的链接,看完了就知道它的基本思想了。求最远路径也是同样的方法,把>改成<就行了。

http://blog.csdn.net/niushuai666/article/details/6791765

看完这个经典算法你就知道了,它可以求是否出现负权回路。同样,它也可以求是否出现正权回路。

而这个题就是要判断对否会出现正权回路。

货币种类N就代表节点数,M个交易点就代表2*M 个边,S是源点,V就是源点最初的距离。

那么就是求源点到各个点的最远的距离(其实也不是),判断是否出现正权回路就行了。

只要稍微想一下,肯定都能想到的。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 111
#define inf -999999
int N,M,S;
double V;
struct Edge
{
    int u,v;
    double r,c;
    Edge(int U=0,int V=0,double R=0.0,double C=0.0)
    {
        u=U,v=V,r=R,c=C;
    }
};
Edge edge[2*MAX];
double dis[MAX];
bool Bellman_Ford(int nodenum,int original,int edgenum)
{
	for(int i = 1; i <= nodenum; ++i) //初始化
		dis[i] = (i == original ? V: inf);
	for(int i = 1; i <= nodenum-1; ++i)
		for(int j = 1; j <= edgenum; ++j)
			if(dis[edge[j].v] <(dis[edge[j].u]-edge[j].c)*edge[j].r) //松弛(顺序一定不能反~)
			{
				dis[edge[j].v] =(dis[edge[j].u]-edge[j].c)*edge[j].r;
			}
    bool flag = 1; //判断是否含有正权回路
    for(int i = 1; i <= edgenum; ++i)
        if(dis[edge[i].u]>0)  //这个判断很重要,负数代表没有连通,就没有必要判断了。否则WA
        if(dis[edge[i].v] <(dis[edge[i].u]-edge[i].c)*edge[i].r)
        {
            flag = 0;
            break;
        }
    return flag;
}
int main()
{
    int i,j=1;
    int A,B;
    double rab,cab,rba,cba;
    scanf("%d%d%d%lf",&N,&M,&S,&V);
    for(i=1;i<=M;i++)
    {
        scanf("%d%d%lf%lf%lf%lf",&A,&B,&rab,&cab,&rba,&cba);
        edge[j++]=Edge(A,B,rab,cab);
        edge[j++]=Edge(B,A,rba,cba);
    }
    if(Bellman_Ford(N,S,j-1)) printf("NO\n");
    else printf("YES\n");
}

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/u013983192/article/details/37939407
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞