W的火星工程

题目

题目描述

大老板W的伟大工程扩大到了火星,他准备在火星建立一个自己的度假村
在他的度假村里,有两个大饭店A,B
对于W来说,修建度假村必不可少的就是从A饭店向B饭店修路,以保证他可以短时间内享受各种美味
火星上有一些中转站,中转站之间以及它们与饭店之间有路径使得能从一个到达另一个(路径为单向)
对于每一条路径,工程师ZQ给出了它的两个消费参数$a,b$
W会从A饭店出发,经过其中的一些路径,最终到达B饭店
W希望他走过的所有道路的$\frac{\sum{a}}{\sum{b}}$最小,也就是那些道路的$a$值之和除以他们的$b$值之和最小
可是路径实在太多了,W不知道该如何选择
聪明的你需要帮助他计算出这个最小值
至于路径的选取方法你就不需要告诉他了

输入格式

输入两个整数$n,m$,表示中转站的数量和边的数量
随后$m$行,每行四个整数$x,y,a,b$,分别表示路径的两端,路径的$a,b$消费参数
其中$0$号点与$n+1$号点分别表示W的两个饭店AB
注意你并不需要把所有中转站都连入路中,只要保证从A饭店可以到达B饭店就行了

输出格式

输出一个小数,表示所求的最小值。误差不超过$10^{-6}$即可

样例

样例输入

2 3
0 1 1 2
0 2 2 3
1 3 1 3

样例输出

0.400000

数据范围与提示

对于$20 %$的数据,$n,m \leqslant 100$
对于$50 %$的数据,$n \leqslant 1000$
对于$100 %$的数据, $1 \leqslant n \leqslant 10000,1 \leqslant m \leqslant 100,000,0 \leqslant x,y \leqslant n+1$
数据保证$0$号饭店可以到达$n+1$号饭店,任意两个中转站或饭店间最多有一条边,且保证没有路可以构成环

题解

0/1分数规划裸题
考虑二分答案,记$dis_i$表示从0到i的路径$\sum a_i-b_i\times mid$的最小值,用类似最短路的方法更新,判断一下$dis_{n+1}$的值是否大于$0$,更改二分的范围
附上代码:

#include<cstdio>
#include<queue>
using namespace std;
int n,m,tot,nxt[100010],head[10010],to[100010],a[100010],b[100010],v[100010];
double L,R=1e9,w[100010],dis[100010];
void add(int u,int v)
{
    nxt[++tot]=head[u],head[u]=tot,to[tot]=v;
}
int pd(double x)
{
    for(int i=0;i<n+2;i++) dis[i]=1e9,v[i]=0;
    for(int i=1;i<=m;i++) w[i]=(double)a[i]-(double)b[i]*x;
    queue<int> q;
    dis[0]=0,q.push(0);
    while(!q.empty()){
        int x=q.front();
        q.pop(),v[x]=0;
        for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]>dis[x]+w[i]){
            dis[to[i]]=dis[x]+w[i];
            if(!v[to[i]]) q.push(to[i]);
            v[to[i]]=1;
        }
    }
    return dis[n+1]>=0;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,u,v;i<=m;i++) scanf("%d%d%d%d",&u,&v,&a[i],&b[i]),add(u,v);
    while(L+0.000000001<R){
        double mid=(L+R)/2;
        if(pd(mid)) L=mid;
        else R=mid;
    }
    printf("%.6lf",L);
}

喜欢的话,给博主赏一杯冰阔乐吧~


  转载请注明: Maserhe W的火星工程

 上一篇
Tree Tree
题目题目描述 输入格式 输出格式 样例样例输入3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE样例输出1 3题解SP375的变体,树链剖分好题一个lazy标志传递错误让我调了半天……先把边
2020-03-26
下一篇 
splay.one splay.one
题目题目描述 某神犇正在打splay.one,打出了$0-233$的超鬼战绩,并为之愤怒神犇怎么可能超鬼呢?神犇立马黑进了服务器,把if(x≤0) 死亡;(x为生命值)这句话删掉了神犇觉得不太好,就改成了if(x==0) 死亡;众所周知神犇
2020-03-18
  目录