洛谷 P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题解

题面

这道题是一道标准的01分数规划:

但是有一些细节可以优化:

不难想到要二分一个mid然后判定图上是否存在一个环S,该环是否满足∑i=1t(Fun[vi]−mid∗Tim[ei])>0

但是上面的算法并不好实现,所以可以将两边同时乘上-1,使式子变为i=1t(midTim[ei]Fun[vi])<0

那么该问题就转化成了在每一个图中跑一边SPFA来寻找是否存在负环,若存在则l=mid,否则r=mid;

#include <bits/stdc++.h>
#define inc(a,b,c) for(register int i=a;i<=b;i+=c)
#define ini 20010
using namespace std;
int n,m;
struct littlestar{
    int from;
    int to;
    int nxt;
    double w;
}star[ini],star2[ini];
int head[ini],cnt,head2[ini];
void add(int u,int v,int w)
{
    star[++cnt].to=v;
    star[cnt].nxt=head[u];
    star[cnt].from=u;
    star[cnt].w=w;
    head[u]=cnt;
}
int c[ini];
queue<int> q;
double dis[ini];
int vis[ini];
int SPFA()
{
    int tot=0;
    for(int i=1;i<=n;i++){
        q.push(i);
        dis[i]=0;
        vis[i]=1;
    }
    while(q.size()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head2[u];i;i=star2[i].nxt){
            int v=star2[i].to;
            if(dis[v]>dis[u]+star2[i].w){
                dis[v]=dis[u]+star2[i].w;
                if(vis[v]==0){
                    vis[v]=1;
                    q.push(v);
                    ++tot;
                    if(tot>2*(n+m)) return 0;
                }
            }
        }
    }
    return 1;
}
int check(double x)
{
    inc(1,cnt,1){
        star2[i]=star[i];
        star2[i].w=(double)star[i].w*(double)x-(double)c[star[i].from];
    }
    inc(1,n,1){
        head2[i]=head[i];
    }
    if(SPFA()){
        return 0;
    }
    else{
        return 1;
    }
}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int main()
{
    n=read();
    m=read();
    inc(1,n,1) c[i]=read();
    inc(1,m,1){
        int u,v,w;
        u=read();v=read();w=read();
        add(u,v,w);
    }
    double l=0.00,r=1000010.000,mid;
    while(r-l>1e-4){
        mid=(l+r)/2;
        if(check(mid)){
            l=mid;
        }
        else{
            r=mid;
        }    
    }
    printf("%.2lf",l);
} 

猜你喜欢

转载自www.cnblogs.com/kamimxr/p/11545032.html