题意就是 现在有N种货币 , 你有其中一种S , 和这种S货币的数量W
M行,每行都是其中一个城市 可以相互兑换的两种货币 A && B ,正汇率Rab , 正汇率兑换费Cab , 反贿赂Rba , 反贿赂兑换费Cba
问 能不能最后换回 货币S 的时候,钱数比原来多(其实就是类似老电视剧里的倒爷,或者买卖黄金赚钱)
一开始没想到就是判断正环,就是任意一种货币在 兑换循环中(循环中可能有多种货币的参与)实现了正增长,只要有正增长,就能一直换钱,换到 正无穷 那么必定换回原来的 货币S ,S的数量是比以前多的。
就是太菜了,冒得解释
但是后来想考虑如果一开始 连 换其他货币的兑换费都付不起怎么办
后来一想,汇率C都付不起 , (dist[u] - C) * R 也小于零 , 没问题
那直接匡斌的板子里 找了bellman-ford算法的板子
改了正环判(因为原本是判负环)直接贴个匡斌的板子,然后贴个本题代码。
const int INF=0x3f3f3f3f;
const int MAXN=550;
int dist[MAXN];
struct Edge{
int u,v;
int cost;
Edge(int _u=0,int _v=0,int _cost=0):u(_u),v(_v),cost(_cost){}
};
vector<Edge>E;
//点的编号从 1 开始
bool bellman_ford(int start,int n){
for(int i=1;i<=n;i++)dist[i]=INF;
dist[start]=0;
//最多做 n-1 次
for(int i=1;i<n;i++){
bool flag=false;
for(int j=0;j<E.size();j++){
int u=E[j].u;
int v=E[j].v;
int cost=E[j].cost;
if(dist[v]>dist[u]+cost){
dist[v]=dist[u]+cost;
flag=true;
}
}
if(!flag)return true;//没有负环回路
}
for(int j=0;j<E.size();j++)
if(dist[E[j].v]>dist[E[j].u]+E[j].cost)
return false;//有负环回路
return true;//没有负环回路
}
本题代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include <set>
#include <vector>
#include <stack>
#define Clear( x , y ) memset( x , y , sizeof(x) );
#define Qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long LL;
const int Maxn = 1e6 + 7;
const int Inf = 1e9 + 7;
int N , M , S;
double W;
const int INF=0x3f3f3f3f;
double dist[Maxn];
struct Edge{
int u , v;
double R , C;
Edge(int _u=0,int _v=0,double _R=0,double _C = 0):u(_u),v(_v),R(_R),C(_C){}
};
vector <Edge> E;
//点的编号从 1 开始
bool bellman_ford(int start , int n){
for(int i = 1 ; i <= n ; i++) dist[i] = 0;
dist[start] = W;
//最多做 n-1 次
for(int i = 1 ; i < n ; i++){
bool flag = false;
for(int j = 0 ; j < E.size() ; j++){
int u = E[j].u;
int v = E[j].v;
double R = E[j].R;
double C = E[j].C;
if(dist[v] < (dist[u] - C) * R){
dist[v] = (dist[u] - C) * R;
flag = true;
}
}
if(!flag) break;
}
for(int i = 0 ; i < E.size() ; i++){
if(dist[E[i].v] < (dist[E[i].u] - E[i].C) * E[i].R)
return true;
}
return false;
}
int main()
{
while(~scanf(" %d %d %d %lf",&N ,&M ,&S ,&W)){
E.clear();
int u , v;
double Rab , Cab , Rba , Cba;
for(int i = 1 ; i <= M ; i++){
scanf(" %d %d %lf %lf %lf %lf",&u ,&v ,&Rab ,&Cab ,&Rba ,&Cba);
E.push_back((Edge){u ,v ,Rab, Cab});
E.push_back((Edge){v ,u ,Rba, Cba});
}
if(bellman_ford(S,N)) printf("YES\n");
else printf("NO\n");
}
}