思路:题目给出n,m,起点S和起点的初始值V,接着m行,每行给出a 兑换成 b需要的佣金和汇率和b兑换到a的佣金和汇率,这里用 a ,b ,ra ,ca ,rb ,cb 表示;
让判断从起点S开始和其他货币进行兑换,最后兑换回S,是否能使得原有的钱变多,就是判断是否存在正环的问题。
spfa算法:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 110, M = 500;
int n,m,s;
int h[N],e[M],ne[M],idx;
double wr[M],wc[M],rv;
double dist[N];
int q[N],cnt[N];
bool st[N];
void add(int a,int b,double r,double c){
e[idx] = b; wr[idx] = r; wc[idx] = c; ne[idx] = h[a]; h[a] = idx++;
}
bool spfa(){
int hh = 0, tt = 1;
dist[s] = rv;
q[0] = s;
st[s] = true;
while(hh != tt){
int t = q[hh++];
if(hh == N) hh = 0;
st[t] = false;
for(int i = h[t]; ~i; i = ne[i]){
int j = e[i];
if(dist[j] < (dist[t] - wc[i]) * wr[i]){
dist[j] = (dist[t] - wc[i]) * wr[i];
cnt[j] = cnt[t] + 1;
if(cnt[j] >= n) return true;
if(!st[j]){
q[tt++] = j;
if(tt == N) tt = 0;
st[j] = true;
}
}
}
}
return false;
}
int main(int argc, char** argv) {
scanf("%d%d%d%lf",&n,&m,&s,&rv);
memset(h,-1,sizeof h);
for(int i = 0; i < m; i++){
int a,b;
double ra,ca,rb,cb;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&ra,&ca,&rb,&cb);
add(a,b,ra,ca);
add(b,a,rb,cb);
}
if(spfa()) puts("YES");
else puts("NO");
return 0;
}
Bellman_ford算法:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 500;
struct Edge{
int a,b;
double r,c;
}edges[N];
int n,m,s;
double dist[N],backup[N],rs;
bool Bellman_ford(){
for(int i = 1; i <= n; i++) dist[i] = 0;
dist[s] = rs;
for(int i = 0; i < n; i++){
for(int i = 1; i <= n; i++) backup[i] = dist[i];
for(int j = 0; j < m; j++){
Edge e = edges[j];
if(dist[e.b] < (backup[e.a] - e.c) * e.r){
dist[e.b] = (backup[e.a] - e.c) * e.r;
if(i == n - 1) return true;
}
}
}
return false;
}
int main(){
while(~scanf("%d%d%d%lf",&n,&m,&s,&rs)){
int cnt = 0;
for(int i = 0; i < m; i++){
int a,b;
double ra,ca,rb,cb;
scanf("%d%d%lf%lf%lf%lf",&a,&b,&ra,&ca,&rb,&cb);
edges[cnt].a = a; edges[cnt].b = b;
edges[cnt].r = ra; edges[cnt++].c = ca;
edges[cnt].a = b; edges[cnt].b = a;
edges[cnt].r = rb; edges[cnt++].c = cb;
}
m = cnt;
if(Bellman_ford()) puts("YES");
else puts("NO");
}
return 0;
}