poj Sightseeing Cows 分数规划+spfa

分数规划的标准做法,先二分答案,然后spfa找正环。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e3+9,maxm=5e3+9;
double a[maxn];
int head[maxn],lon;
struct
{
    int to,next,w;
}e[maxm<<1];
void edgeini()
{
    memset(head,-1,sizeof(head));
    lon=-1;
}
void edgemake(int from,int to,int w)
{
    e[++lon].to=to;
    e[lon].w=w;
    e[lon].next=head[from];
    head[from]=lon;
}

int n,m,que[maxn*maxn],in[maxn];
double dist[maxn];
bool text[maxn];
bool spfa(double ret)
{
    int front=1,end=0;
    for(int i=1;i<=n;i++)
    {
        que[++end]=i;
        dist[i]=in[i]=0;
        text[i]=1;
    }
    while(front<=end)
    {
        int t=que[front++];
        if(in[t]>n)
        return true;
        text[t]=0;
        for(int k=head[t];k!=-1;k=e[k].next)
        {
            int u=e[k].to;
            if(dist[u]<dist[t]+a[u]-ret*e[k].w)
            {
                dist[u]=dist[t]+a[u]-ret*e[k].w;
                if(!text[u])
                {
                    text[u]=1;
                    que[++end]=u;
                    in[u]++;
                }
            }
        }
    }
    return false;
}

int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        edgeini();
        for(int i=1;i<=n;i++)
        scanf("%lf",&a[i]);
        for(int i=1,from,to,w;i<=m;i++)
        {
            scanf("%d %d %d",&from,&to,&w);
            edgemake(from,to,w);
        }
        double l=0,r=1e3+9,m;
        while(r-l>1e-4)
        {
            m=(l+r)/2;
            if(spfa(m)) l=m;
            else r=m;
        }
        printf("%.2f\n",l);
    }
    return 0;
}


你可能感兴趣的:(poj Sightseeing Cows 分数规划+spfa)