您的位置:首页 > 其它

POJ 1860 Currency Exchange(SPFA 判断有无“正”环)

2015-09-07 21:35 337 查看
题目链接:POJ 1860 Currency Exchange

【题目大意】

货币转换问题,给你初始金额还有货币种类。然后给你货币之间的汇率及手续费(转换时额外的花销)。问能否通过货币间的转换实现自己的本金增大。

将dis 数组初始化为0

用 SPFA不断 的进行松弛操作, 发现当前金额可以比本身大, 就更新,同时记录更新次数。如果更新次数超过n次,说明存在”正“环。

这里先说明下负环。(求最短距离的时候)



在我们用SPFA求最短路径的时候,如果存在负环,在松弛操作的时候总会加入队列 因为最小距离会越来越小,同样这里如果经过一次次的转换,如果可以使本金增大,那么松弛操作也会无限进行下去,我们以n为界限,超过n就说明存在正环,也就说明可以使本金增大。

【源代码】

#include <queue>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int V = 3000;
const int E = 1500;
const double INF = 10000000.0;
struct node{
	int v,next;
	double R,C;
}pnt[E];
int head[V];
double dis[V]; // no idea
bool vis[V];
int cnt[V];
int e = 0;
int N,M;
int src;
double val;
void addedge(int u,int v,double R, double C){
	pnt[e].v = v; 
	pnt[e].R = R; pnt[e].C = C;
	pnt[e].next = head[u];
	head[u] = e++;
}
void init(){
    e=0;
    memset(head, -1,sizeof(head));
    memset(vis, 0 ,sizeof(vis));
    memset(cnt, 0 ,sizeof(cnt));
    for(int i=0; i<=N; i++) dis[i] = 0;
}
int SPFA(){
	queue<int>Q;
	Q.push(src) ; vis[src] = 1;dis[src] = val; ++cnt[src];
	while(!Q.empty()){
		int u = Q.front(); Q.pop(); vis[u] = 0;
		for(int i=head[u] ; i!=-1 ; i=pnt[i].next){
			int v = pnt[i].v;
			double tmp =  (dis[u]-pnt[i].C)*pnt[i].R; //当前位置可能变成的值
			             //本金 减去利息 再乘汇率;
			if(dis[v] <tmp){ //如果比原来大 
				dis[v] = tmp;
				if(!vis[v]){ Q.push(v) ; vis[v] = 1;}
				if(++cnt[v] > N) return -1; //negative cycle
				 //如果一个点能变大N次以上 。 说明他还能继续增大,说明原值已经可以通过转换增大
			}
		}
	}
	return 1;
}
 
int main(){
	
	scanf("%d%d",&N,&M);
	scanf("%d",&src);
	scanf("%lf",&val);
	init();
	int a,b;
	double Rab,Rba,Cab,Cba;
	for(int i=0;i<M;i++){
		scanf("%d%d",&a,&b);
		scanf("%lf%lf%lf%lf",&Rab,&Cab,&Rba,&Cba);
		addedge(a,b,Rab,Cab);
		addedge(b,a,Rba,Cba);
	}
	int ret = SPFA();
	if(ret == -1)
		cout<<"YES"<<endl;
	else
		cout<<"NO"<<endl;
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: