浴谷 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。

 

输入输出样例

输入样例#1:
5 6
1 2 1 1
4 1 6 2
5 4 8 1
2 3 2 2
5 2 4 1
3 5 6 4
输出样例#1:
2.3

说明

对于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分数规划。

尽管加上了各种优化,还是只能拿80分。

#include<deque>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50010
using namespace std;
int n,m,tot;
double l,r,mid;
double intrest[MAXN],cap[MAXN],dis[MAXN];
int to[MAXN],head[MAXN],net[MAXN],vis[MAXN],num[MAXN];
inline int read(){
    char ch=getchar();int data=0;
    while(ch<'0'||ch>'9') ch=getchar();
    do{
        data=data*10+ch-'0';
        ch=getchar();
    }while(ch>='0' && ch<='9');
    return data;
}
inline void add(int u,int v,double w,double p){
    to[++tot]=v;net[tot]=head[u];intrest[tot]=w;cap[tot]=p;head[u]=tot;
}
inline bool spfa(int s){
    deque<int>que;
    memset(vis,0,sizeof(vis));
    memset(num,0,sizeof(num));
    memset(dis,0x7f,sizeof(dis));
    que.push_back(s);
    dis[s]=0;vis[s]=1;num[s]++;
    while(!que.empty()){
        int now=que.front();
        que.pop_front();
        vis[now]=0;
        for(int i=head[now];i;i=net[i])
            if(dis[to[i]]>dis[now]+mid*cap[i]-intrest[i]){
                dis[to[i]]=dis[now]+mid*cap[i]-intrest[i];
                if(!vis[to[i]]){
                    if(dis[to[i]]>dis[now])    que.push_back(to[i]);
                    else    que.push_front(to[i]);
                    vis[to[i]]=1;
                    num[to[i]]++;
                    if(num[to[i]]>n)    return true;
                }
            }
    }
    return false;
}
inline bool check(double x){
    if(spfa(0))    return true;
    else return false;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=m;i++){
        int x,y;double v,p;
        x=read();y=read();
        scanf("%lf%lf",&v,&p);
        add(x,y,v,p);
    }
    for(int i=1;i<=n;i++)    add(0,i,0,0);
    l=0;r=200;
    while(r-l>0.01){
        mid=(l+r)/2;
        if(check(mid))    l=mid;
        else r=mid;
    }
    if(l==0)    cout<<"-1";
    else printf("%.1lf",r);
}
bfs的spfa判负环

dfs判负环AC    19ms

#include<deque>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50010
using namespace std;
int n,m,tot;
double l,r,mid,ans;
double intrest[MAXN],cap[MAXN],dis[MAXN];
int to[MAXN],head[MAXN],net[MAXN],vis[MAXN];
inline void add(int u,int v,double w,double p){
    to[++tot]=v;net[tot]=head[u];intrest[tot]=w;cap[tot]=p;head[u]=tot;
}
bool spfa(int now){
    vis[now]=1;
    for(int i=head[now];i;i=net[i])
        if(dis[to[i]]>dis[now]+mid*cap[i]-intrest[i]){
            dis[to[i]]=dis[now]+mid*cap[i]-intrest[i];
            if(vis[to[i]]||spfa(to[i])){
                vis[to[i]]=0;
                return true;
            }
        }
    vis[now]=0;
    return false;
}
inline bool check(double x){
    for(int i=1;i<=n;i++)
        if(spfa(i))    return true;
    return false;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;double v,p;
        scanf("%d%d",&x,&y);
        scanf("%lf%lf",&v,&p);
        add(x,y,v,p);
    }
    l=0;r=200;
    while(r-l>0.01){
        mid=(l+r)/2;
        if(check(mid)){
            ans=mid;
            l=mid;
        }    
        else r=mid;
    }
    if(l==0)    cout<<"-1";
    else printf("%.1lf",ans);
}

对比一下spfa的bfs判负环和dfs判负环的时间复杂度:

这些是bfs的尽管加上了各种优化还以一直TLE

而下面的:

  第一行是没加读入优化的dfs。

  第二行是加上读入优化的dfs。

 dfs的速度秒杀bfs

细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/7681638.html