题目链接:https://cn.vjudge.net/problem/POJ-1860
题目
第一行,n种货币,m个关系, 你拥有的货币种类以及数量。接下来m行,每行六个数,a,b,c,d,e,f,表示a换成b需要本金减去d,再乘以汇率c,b换成a需要减去f,再乘以汇率e。问你有没有可能交换一圈后货币数量增加。
分析
首先建立边,例如a->b,起点是a,终点是b,这条边的汇率是c,需要减去的钱是d,其他边也这样建。建好边后spfa一遍就可以了,spfa里面每次找能让货币数量增加的边。
代码
#include<iostream>
#include<cstdio>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
int n,m,s,cnt,head[1110];
double v,dis[1110];
bool vis[1110];
struct node{
int to,nxt;
double lv,pay;
}edge[1110];
void add(int a,int b,double lv,double pay)
{
edge[cnt].to = b;
edge[cnt].lv = lv;
edge[cnt].pay = pay;
edge[cnt].nxt = head[a];
head[a] = cnt++;
}
void spfa()
{
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)
dis[i] = -1.0;
dis[s] = v;
queue<int> q;
q.push(s);
vis[s] = 1;
while(!q.empty())
{
int t = q.front();
q.pop();
vis[t] = 0;
for(int i=head[t];i!=-1;i=edge[i].nxt)
{
int num = edge[i].to;
double sum = (dis[t] - edge[i].pay) * edge[i].lv;
if(dis[num] < sum)//能增加,选择
{
dis[num] = sum;
q.push(num);
vis[num] = 1;
}
}
}
}
int main()
{
cnt = 0;
memset(head,-1,sizeof head);
scanf("%d%d%d%lf",&n,&m,&s,&v);
for(int i=0;i<m;i++)
{
int a,b;
double lv,pay;
scanf("%d%d%lf%lf",&a,&b,&lv,&pay);
add(a,b,lv,pay);
scanf("%lf%lf",&lv,&pay);
add(b,a,lv,pay);
}
spfa();
if(dis[s] > v) printf("YES\n");
else printf("NO\n");
return 0;
}