poj1860 兌換貨幣(bellman ford判斷正環)

傳送門:點擊打開鏈接

題目大意:一個城市有n種貨幣,m個貨幣交換點,你有v的錢,每個交換點只能交換兩種貨幣,(A換B或者B換A),每一次交換都有獨特的匯率和手續費,問你存不存在一種換法使原來的錢更多。

思路:一開始以爲一個地方只能用一次,感覺好像有點難,後來發現自己讀錯題了,其實只要判斷給你的這幅圖存不存在正環就可以了,用dis【】表示某種貨幣的數量,然後bellman判斷正環就可以了。(題目裏強調結尾一定要原來的貨幣,但其實這是廢話,因爲是以原來的貨幣爲起點的,所以你換出去了一定換的回來),正環指的是跑一圈w變大的環。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<math.h>
#include<cmath>
#include<time.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<algorithm>
#include<numeric>
using namespace std;
int n,m,s,num;
const int maxn=110;
double V,dis[maxn];
struct edge{
	int u,v;
	double cost,w;
}e[220];
void addv(int a,int b,double ra,double ca){
	e[num].u=a;
	e[num].v=b;
	e[num].cost=ca;
	e[num++].w=ra;
}
bool bellman(){
	dis[s]=V;
	for(int i=1;i<n;i++){//鬆弛n-1次  
	bool flag=false;
		for(int j=0;j<num;j++){
			int u=e[j].u;
			int v=e[j].v;
			if(dis[v]<(dis[u]-e[j].cost)*e[j].w){
				dis[v]=(dis[u]-e[j].cost)*e[j].w;
				flag=true;
			}
		}
		if(!flag)return false;// 如果n-1次都無法鬆弛   那肯定不存在正環 
	}
	for(int i=0;i<num;i++){
		if(dis[e[i].v]<(dis[e[i].u]-e[i].cost)*e[i].w)//第n次若能鬆弛  說明存在正環 
		return true; 
	}
	return false;
}
int main(){
	while(scanf("%d%d%d%lf",&n,&m,&s,&V)!=EOF){
	num=0;
	sizeof(dis,0,sizeof(dis));

	while(m--){
		int a,b;
		double ra,ca,rb,cb;
		scanf("%d%d%lf%lf%lf%lf",&a,&b,&ra,&ca,&rb,&cb);
		addv(a,b,ra,ca);
		addv(b,a,rb,cb);
	}
	if(bellman())printf("YES\n");
	else printf("NO\n");
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章