POJ 1860 汇率 SPFA

泪湿孤枕 提交于 2019-12-01 05:28:07

题意

有多种汇币,汇币之间可以交换,这需要手续费,当你用100A币交换B币时,A到B的汇率是29.75,手续费是0.39,那么你可以得到(100 - 0.39) * 29.75 = 2963.3975 B币。问s币的金额经过交换最终得到的s币金额数能否增加 货币的交换是可以重复多次的,所以我们需要找出是否存在正权回路,且最后得到的s金额是增加的 怎么找正权回路呢?(正权回路:在这一回路上,顶点的权值能不断增加即能一直进行松弛)

Sample Input

3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00

Sample Output

YES

对SPFA算法进行改造,原来的dis改为存的货币的数量,改为求最长路,如果有自环,那么dis会不断增加没有上限

if(money[v]<(money[u]-E[u][i].fee)*E[u][i].rate){
    money[v]=(money[u]-E[u][i].fee)*E[u][i].rate;
    if(!vis[v])
#define _CRT_SBCURE_NO_DEPRECATE
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <bitset>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define ll long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
#define each(a,b,c) for(int a=b;a<=c;a++)
#define de(x) cout << #x << " " << (x) <<endl
//#define de(x) cout <<""
#define rush() int T;scanf("%d",&T);each(kase,1,T)
#define scan(a,b) scanf("%d%d",&a,&b)
#define fin(a) scanf("%d",&a)
using namespace std;

const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}

/*
3 2 1 20.0
1 2 1.00 1.00 1.00 1.00
2 3 1.10 1.00 1.10 1.00
*/
struct Edge{
    int v;
    double fee;
    double rate;
    Edge(int _v,double _fee,double _rate):v(_v),fee(_fee),rate(_rate){}
};
vector<Edge>E[maxn];
void addEdge(int u,int v,double fee,double rate)
{
    E[u].push_back(Edge(v,fee,rate));
}
bool vis[maxn];
int cnt[maxn];
double money[maxn];

int n;
int m;
int start;
double init_money;
bool SPFA(int start,double init_money,int n)
{
    memset(vis,false,sizeof(vis));//清空vis
    for(int i=1;i<=n;i++)money[i]=0;
    vis[start]=true;
    money[start]=init_money;
    queue<int>Q;
    while(!Q.empty())Q.pop();
    Q.push(start);
    memset(cnt,0,sizeof(cnt));
    cnt[start]=1;
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        vis[u]=false;
        for(int i=0;i<E[u].size();i++)
        {
            int v=E[u][i].v;
            if(money[v]<(money[u]-E[u][i].fee)*E[u][i].rate){
                money[v]=(money[u]-E[u][i].fee)*E[u][i].rate;
                if(!vis[v])
                {
                    vis[v]=true;
                    Q.push(v);
                    if(++cnt[v]>n)return false;
                }
            }
        }

    }
    return true;
}
int main()
{
    scanf("%d%d%d%lf",&n,&m,&start,&init_money);
    each(i,1,m)
    {
        int a,b;
        double rab,cab,rba,cba;
        scan(a,b);
        scanf("%lf%lf%lf%lf",&rab,&cab,&rba,&cba);
        addEdge(a,b,cab,rab);
        addEdge(b,a,cba,rba);
    }
    if(!SPFA(start,init_money,n))
        cout<<"YES"<<endl;
    else cout<<"NO"<<endl;

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!