【Luogu】P3288方伯伯运椰子(消圈定理)

  题目链接

  分数规划题,详见luogu题解

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define maxn 100010
#define eps 1e-9
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

struct Edge{
    int next,to;double val;
}edge[maxn*2];
int head[maxn],num;
inline void add(int from,int to,double val){
    edge[++num]=(Edge){head[from],to,val};
    head[from]=num;
}

bool vis[maxn];
double dis[maxn];

bool spfa(int x,double mid){
    vis[x]=1;
    for(int i=head[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(dis[to]<=dis[x]+edge[i].val+mid)    continue;
        dis[to]=dis[x]+edge[i].val+mid;
        if(vis[to])    return 1;
        if(spfa(to,mid))    return 1;
    }
    vis[x]=0;
    return 0;
}
int n,m;
bool check(double mid){
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;++i)
        if(spfa(i,mid))    return 1;
    return 0;
}

int main(){
    n=read()+2,m=read();
    for(int i=1;i<=m;++i){
        int from=read(),to=read(),a=read(),b=read(),c=read(),d=read();
        if(c!=0)    add(to,from,a-d);
        add(from,to,b+d);
    }
    double l=0,r=0x7fffffff,ans=0;
    while(fabs(r-l)>eps){
        double mid=(l+r)/2.0;
        if(check(mid)){
            ans=mid;
            l=mid;
        }
        else r=mid;
    }
    printf("%.2lf",ans);
    return 0;
}

 

posted @ 2018-05-03 08:17 Konoset 阅读(...) 评论(...) 编辑 收藏