1. 程式人生 > >POJ 1860 Currency Exchange spfa

POJ 1860 Currency Exchange spfa

注意,使用spfa演算法的時候,一個點進隊n+2次說明所有與其相關的點均已經得到了正環的收益,然而除此之外什麼都不能說明,在這道題上,也就不可能說明此時某點的值是否可以大於它的初始值。spfa是個神奇的演算法,的空一定要好好研究一番。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

struct Edge
{
    int to,nex;
    double c,r;
}edge[220];

int e,head[110],inq[110],vis[110],n,m,s;
double v,d[110];

void addedge(int a,int b,double rr,double cc)
{
    edge[e].to=b;
    edge[e].r=rr;
    edge[e].c=cc;
    edge[e].nex=head[a];
    head[a]=e++;
    //cout<<"a="<<a<<" b="<<b<<" r="<<rr<<" c="<<cc<<endl;
}

int spfa(int s)
{
    queue<int> q;
    memset(inq,0,sizeof(inq));
    memset(vis,0,sizeof(vis));
    memset(d,0,sizeof(d));
    d[s]=v;
    inq[s]=1;
    q.push(s);
    int tmp=s;
    while (!q.empty())
    {
        s=q.front(); q.pop();
        vis[s]++;
        inq[s]=0;
        //cout<<"s="<<s<<" vis="<<vis[s]<<endl;
        if (d[tmp]>v) return true;
        if (vis[s]==n+2) continue;
        for (int i=head[s]; i!=-1; i=edge[i].nex)
        {
            int v=edge[i].to;
            //cout<<"s="<<s<<" v="<<v<<" d="<<d[v]<<" d2="<<(d[s]-edge[i].c)*edge[i].r<<endl;
            //cout<<"ds="<<d[s]<<" c="<<edge[i].c<<" r="<<edge[i].r<<endl;
            if (d[v]<(d[s]-edge[i].c)*edge[i].r)
            {
                d[v]=(d[s]-edge[i].c)*edge[i].r;
                if (!inq[v])
                {
                    inq[v]=1; q.push(v);
                }
            }
            //if (d[tmp]>v) return true;
        }
    }
    return false;
}

int main()
{
    while (~scanf("%d%d%d%lf",&n,&m,&s,&v))
    {
        e=0;
        memset(head,-1,sizeof(head));
        for (int i=1; i<=m; i++)
        {
            int a,b;
            double rab,cab,rba,cba;
            scanf("%d%d%lf%lf%lf%lf",&a,&b,&rab,&cab,&rba,&cba);
            addedge(a,b,rab,cab);
            addedge(b,a,rba,cba);
        }
        if (spfa(s)) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}