luogu P1768 天路

题目描述

“那是一条神奇的天路诶~,把第一个神犇送上天堂~”,XDM先生唱着这首“亲切”的歌曲,一道猥琐题目的灵感在脑中出现了。

和C_SUNSHINE大神商量后,这道猥琐的题目终于出现在本次试题上了,旨在难到一帮大脑不够灵活的OIer们(JOHNKRAM真的不是说你……)。

言归正传,小X的梦中,他在西藏开了一家大型旅游公司,现在,他要为西藏的各个景点设计一组铁路线。但是,小X发现,来旅游的游客都很挑剔,他们乘火车在各个景点间游览,景点的趣味当然是不用说啦,关键是路上。试想,若是乘火车一圈转悠,却发现回到了游玩过的某个景点,花了一大堆钱却在路上看不到好的风景,那是有多么的恼火啊。

所以,小X为所有的路径定义了两个值,Vi和Pi,分别表示火车线路的风景趣味度和乘坐一次的价格。现在小X想知道,乘客从任意一个景点开始坐火车走过的一条回路上所有的V之和与P之和的比值的最大值。以便为顾客们推荐一条环绕旅游路线(路线不一定包含所有的景点,但是不可以存在重复的火车路线)。

于是,小X梦醒之后找到了你……

输入格式

第一行两个正整数N,M,表示有N个景点,M条火车路线,火车路线是单向的。

以下M行,每行4个正整数,分别表示一条路线的起点,终点,V值和P值。

注意,两个顶点间可能有多条轨道,但一次只能走其中的一条。

输出格式

一个实数,表示一条回路上最大的比值,保留1位小数。

若没有回路,输出-1。

说明/提示

对于30%的数据,1≤N≤100,1≤M≤20;

对于60%的数据,1≤N≤3,000,1≤M≤2,000;

对于100%的数据,1≤N≤7,000,1≤M≤20,000,1≤Vi,Pi≤1,000.

保证答案在200以内.

01分数规划+负环

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define db double
using namespace std;
const db eps=1e-2;
const int N=7e3+10,M=2e4+10,inf=1<<29;
int next[M],head[N],go[M],V[M],P[M],tot;
inline void add(int u,int v,int o1,int o2){
    next[++tot]=head[u];head[u]=tot;go[tot]=v;V[tot]=o1;P[tot]=o2;
}
db dis[N];
bool vis[N];
int used[N];
int s;
int n,m;
inline bool spfa(db ans,int now){
    vis[now]=true;
    for(int i=head[now];i;i=next[i]){
        int v=go[i];
        db x=ans*P[i]-V[i];
        if(dis[v]>dis[now]+x){
            if(vis[v])return 0;
            else{
                dis[v]=dis[now]+x;
                vis[now]=1;
                if(!spfa(ans,v))return 0;
            }
        }
    }
    vis[now]=0;
    return 1;   
}
inline bool check(db x){
    for(int i=1;i<=n;i++){
        dis[i]=inf;
        used[i]=0;
        vis[i]=0;
    }
    return !spfa(x,s);
}
int main(){
    cin>>n>>m;
    db l=0,r=3000,ans=-1;
    for(int i=1,u,v,o1,o2;i<=m;i++){
        scanf("%d%d%d%d",&u,&v,&o1,&o2);
        add(u,v,o1,o2);
    }
    s=n+1;
    for(int i=1;i<=n;i++)add(s,i,0,0);
    while(l+eps<r){
        db mid=(l+r)/2;
        if(check(mid)){
            l=mid;
            ans=mid;
        }else{
            r=mid;
        }
    }
    if(ans==-1)printf("-1\n");
    else 
    printf("%.1f\n",ans);
}

猜你喜欢

转载自www.cnblogs.com/naruto-mzx/p/11625095.html