傳送門:點擊打開鏈接
題目大意:一個城市有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");
}
}