题意:
有n种钱币,m个钱币兑换点,小明一开始有第n种钱币数量为w。
每个兑换点可以将两种不同的钱币相互兑换,但是兑换前要先收取一定的费用,然后按照比例兑换。
问小明是否可以经过一系列的兑换之后能够将持有的第n种钱的数量增加。
这题大概就是看是否存在权值为正的环。如果存在这样的环,那么可以一直循环,然后在适当的时候兑换成第n种钱币。
这种算法一定要看好兑换率的范围!~
思路:
利用SPFA算法,当一个点松弛次数超过N次的时候我们认为存在一个正环。
#include<stdio.h> #include<string.h> #include<queue> using namespace std; int n,m,stc; int ednum; int cnt[105]; double stnum; double dis[105]; bool vis[105]; struct edge { int id; double cost,plu; edge *next; }; edge edges[10005]; edge *adj[105]; inline void addEdge(int a,int b,double c,double d) { edge *tmp; tmp=&edges[ednum]; ednum++; tmp->id=b; tmp->cost=c; tmp->plu=d; tmp->next=adj[a]; adj[a]=tmp; } bool SPFA() { int id; memset(cnt,0,sizeof(cnt)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { dis[i]=-1; } dis[stc]=stnum; queue<int>q; q.push(stc); vis[stc]=1; cnt[stc]++; while(!q.empty()) { id=q.front(); q.pop(); vis[id]=0; for(edge *p=adj[id];p;p=p->next) { if((dis[id]-p->cost>0)&&((dis[id]-p->cost)*p->plu>dis[p->id])) { cnt[p->id]++; if(cnt[p->id]>n)//如果松弛次数超过n次,则说明存在正环 return 1; dis[p->id]=(dis[id]-p->cost)*p->plu; if(!vis[p->id]) { q.push(p->id); vis[p->id]=1; } } } } return 0; } int main() { int a,b; double c,d,e,f; scanf("%d%d%d%lf",&n,&m,&stc,&stnum); for(int i=1;i<=m;i++) { scanf("%d%d%lf%lf%lf%lf",&a,&b,&d,&c,&f,&e); addEdge(a,b,c,d); addEdge(b,a,e,f); } if(SPFA()) printf("YES\n"); else printf("NO\n"); return 0; }
时间: 2024-10-10 04:34:16