NEERC2001,Northern Subregion POJ1860 Currency Exchange 题解


其实本来不想写题解的,但是由于这题把我坑到了,所以就来写个题解。

题目大意

N 中货币,M 个地方可以进行不同货币的转换,每个地方可以转换两种货币 AB,其中两种货币的汇率分别是 RABRBA,交易是需要支付的手续费为 CABCBA,手续费从原来的货币里扣除。现在要问,如果一个人有货币 S V 单位,请问他是否能增加他的资本,当然必须换成货币 S
数据范围 1SN 100 1M100 0V103 102R,C102

解题过程

第一反应:这不是判正环吗?随手写了个SPFA然后。。。

嘿嘿,WA了。难道是我不会写判负环?

上网去看了一下题解,发现他们都是直接判断能不能在货币 S 获得比 V 多的钱。
仔细一看: 102R102,汇率还有负的?!
我也造了一组HACK数据:

3 2 100.0
1 2 1.00 1.00 0.00 0.00
2 3 1.10 1.10 1.10 1.10

显然如果找正环会输出 YES,但是答案显然是 NO,因为从货币 2 到货币 1 的汇率为 0 ,在货币 23 之间获得再多的钱最后也没用。
但是按照 SPFA 的算法,答案最后会在两个节点之间更新最长路,难道不会 TLE 吗?我们发现,在跑的时候钱的数量是指数级增长的,很快就爆 double 了,然后就会变成负的从而结束搜索,最后输出 NO。

最后注意多测数组清空。

代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 139
using namespace std;
//#define debug
typedef int Type;
inline Type read(){
Type sum=0;
int flag=0;
char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar();
if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){
sum=(sum<<1)+(sum<<3)+(c^48);
c=getchar();
}
if(flag) return -sum;
return sum;
}
int head[maxn],nex[maxn<<1],to[maxn<<1],k;
double r[maxn<<1],c[maxn<<1];
#define add(x,y,rx,cx) nex[++k]=head[x];\
head[x]=k; to[k]=y; r[k]=rx; c[k]=cx;
int n,m,x,y;
double rx1,cx1,rx2,cx2;
struct JTZ{
int s;
double v;
}cur;
queue<JTZ> q,E;
int cnt[maxn],vis[maxn],st;
double dist[maxn],v0;
void work(){
cur.s=read(); cin>>cur.v;
st=cur.s; v0=cur.v;
for(int i=1;i<=m;i++){
cin>>x>>y;
cin>>cx1>>rx1>>cx2>>rx2;
add(x,y,rx1,cx1);
add(y,x,rx2,cx2);
}
dist[cur.s]=cur.v;
q.push(cur);
while(!q.empty()){
cur=q.front(); q.pop(); vis[cur.s]=0; cur.v=dist[cur.s];
//printf("%0.2lf\n",cur.v);
for(int i=head[cur.s];i;i=nex[i])
if(dist[to[i]]<(cur.v-r[i])*c[i]&&c[i]>0){
dist[to[i]]=(cur.v-r[i])*c[i];
if(!vis[to[i]]){
cnt[to[i]]++; vis[to[i]]=1;
//if(cnt[to[i]]>n){ printf("YES\n"); return; }
q.push((JTZ){to[i],dist[to[i]]});
}
}
if(dist[st]>v0){
printf("YES\n");
return;
}
}
printf("NO\n");
return;
}
int main(){
//freopen("1.in","r",stdin);
//freopen("my.out","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF){
k=0; memset(dist,0,sizeof(dist));
q=E; memset(cnt,0,sizeof(cnt));
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
work();
}
return 0;
}
posted @   jiangtaizhe001  阅读(49)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示