这道题是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");
}