POJ 1860(最短路之Bellman-Ford)

题目链接:http://poj.org/problem?id=1860

题意:首先给出四个数n,m,s,v,分别表示n种货币,m个兑换关系,s源货币,源货币的本金v

然后给出m行,每行给出6个数beg,end,r1,c1,r2,c2,分别表示beg和end货币兑换的比率和手续费,end和beg货币兑换的比率和手续费

。问能否通过货币兑换使手里的源货币依然是第s中货币,并且本金增多。

思路:感觉如果不是对最短路算法很熟悉的话,这道题很不好做。实际上这道题是Bellman-Ford的变形,求最长路径,利用Bellman-Ford

算法的思想,判断是否存在正环就可以了。具体代码实现如下。

(顺便补充一句,最近刚接触Bellman-Ford算法,感觉像是在Dijsktra算法的基础上增加一层循环判断是否存在负环就可以了,另外,从效率上

来看,个人感觉无负权图优先考虑Dijsktra,带负权图优先考虑SPFA,似乎Bellman-Ford用的地方比较少)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=505;
int n,m,s;
double v;
double dis[maxn];
int e;

struct Edge{
	int u;
	int v;
	double r;
	double c;
}edge[maxn];

void addEdge(int u,int v,double r,double c){
	edge[e].u=u;
	edge[e].v=v;
	edge[e].r=r;
	edge[e].c=c;
	e++;
}

bool relax(int 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;
		return true;
	}
	return false;
}

bool Bellman_Ford(){
	memset(dis,0,sizeof(dis));
	dis[s]=v;
	bool flag;
	for(int i=1;i<n;i++){
		flag=false;
		for(int j=0;j<e;j++){
			if(relax(j))
				flag=true;
		}
		if(dis[s]>v) return true;
		if(!flag) return false;
	}
	for(int k=0;k<e;k++){
		if(relax(k))
			return true;
	}
	return false;
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
#endif
	while(~scanf("%d%d%d%lf",&n,&m,&s,&v)){
		e=0,s--;
		int beg,end;
		double r1,c1,r2,c2;
		for(int i=0;i<m;i++){
			scanf("%d%d%lf%lf%lf%lf",&beg,&end,&r1,&c1,&r2,&c2);
			beg--,end--;
			addEdge(beg,end,r1,c1);
			addEdge(end,beg,r2,c2);
		}
		bool ans=Bellman_Ford();
		if(ans==1) puts("YES\n");
		else puts("NO\n");
	}
	return 0;
}


你可能感兴趣的:(POJ 1860(最短路之Bellman-Ford))