题目描述:
给出一定数量的某种钱币,通过外汇一系列兑换增加钱币数量。
这个“外汇"很扯,A->B和B->A的汇率都能大于1
思路分析:
抽象成图,每种钱币是一个节点,兑换途径就是路径。显然增加钱币数量,图中必须要有一个汇率都大于1的回路,且该回路必须与最初货币连通。那么现在的任务就是,找到这个回路
此题是找正回路,和负回路略有不同但是思路是一样的
B-F算法可以找负回路
B-F的队列优化,SPFA也可以
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <queue>
#include <stack>
#include <string.h>
#include <math.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int MAX=210;
int first[MAX];
int nextn[MAX];
int cnt[110];
int n,m,s;
double v;
int mark[110];
double dis[110];
queue<int>q;
struct node{
int e,s;
double r,c;
}edge[110];
void SPFA(){
memset(mark,0,sizeof(mark));
memset(dis,0,sizeof(dis));
memset(cnt,0,sizeof(cnt));
while(!q.empty())
q.pop();
dis[s]=v;
q.push(s);
int flag=0;
while(!q.empty()){
int a=q.front();
q.pop();
mark[a]=0;
for(int i=first[a];i!=-1;i=nextn[i]){
int x=edge[i].e;
double t=(dis[a]-edge[i].c)*edge[i].r;
//printf("%f-%d--%f\n",t,x,dis[x]);
if(t>dis[x]){
dis[x]=t;
if(!mark[x]){
q.push(x);
mark[x]=1;
cnt[x]++;
//printf("%f*%d\n",dis[x],cnt[x]);
if(cnt[x]>=n)flag=1;
}
}
}
if(flag){
printf("YES\n");
return ;
}
}
printf("NO\n");
}
int main(){
memset(first,-1,sizeof(first));
memset(nextn,-1,sizeof(nextn));
scanf("%d%d%d%lf",&n,&m,&s,&v);
for(int i=0;i<2*m;i++){
int s,e;
double a,b,c,d;
scanf("%d%d%lf%lf%lf%lf",&s,&e,&a,&b,&c,&d);
edge[i].s=s,edge[i].e=e;
edge[i].r=a,edge[i].c=b;
nextn[i]=first[s];
first[s]=i;
i++;
edge[i].s=e,edge[i].e=s;
edge[i].r=c,edge[i].c=d;
nextn[i]=first[e];
first[e]=i;
}
SPFA();
return 0;
}