zoukankan      html  css  js  c++  java
  • 【洛谷p4951】地震 #0/1分数规划入门#

    0/1分数规划入门题:【洛谷p4951】地震 

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cassert>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<deque>
    using namespace std;
    typedef long long ll;
    
    /*【p4951】地震
    将图连通,使总利润(F-成本)和总施工时间的比值最大。 */
    
    /*【0/1分数规划】推式子 + 二分答案 + 最小生成树
    ( f − ∑wi ) / ∑ti ≥ x [即now_mid];化简为:f≥∑(wi+ti*x)。
    每二分一个答案x,求最小生成树的∑(wi+ti*x)是否满足<=f。*/
    
    void reads(int &x){ //读入优化(正负整数)
        ll f=1;x=0;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
        x*=f; //正负号
    }
    
    const int N=1019,M=20019;
    const double eps=1e-6;
    
    int n,m,F,fa[N];
    
    struct Edge{ int u,v,c,t; double w; }a[M];
    
    bool cmp(Edge x,Edge y){ return x.w<y.w; } //最小生成树边集排序
    
    int find_fa(int x){ return (fa[x]==x)?fa[x]:fa[x]=find_fa(fa[x]); }
    
    bool checks(double mid){
        for(int i=1;i<=n;i++) fa[i]=i; //记得并查集清零
        for(int i=1;i<=m;i++) a[i].w=a[i].c+mid*a[i].t;
        sort(a+1,a+m+1,cmp); //边按权值排序
        int cnt_=0; double sum=0;
        for(int i=1;i<=m;i++){ if(cnt_==n-1) break;
            int fx=find_fa(a[i].u),fy=find_fa(a[i].v);
            if(fx!=fy) cnt_++,fa[fx]=fy,sum+=a[i].w;
        } return (sum<=F);
    }
    
    int main(){
        scanf("%d%d%d",&n,&m,&F);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].c,&a[i].t);
        double l=0.0,r=1e9,mid; //↓↓注意实数二分的写法
        while(r-l>1e-6){ mid=(l+r)/2; if(checks(mid)) l=mid; else r=mid; }
        printf("%.4lf
    ",l); return 0;
    }
  • 相关阅读:
    多个div并排显示的居中问题——来自腾讯的一道面试题
    c++ 类的对象与指针
    c++ 联合体
    用户输入一个数字,找到所有能够除尽它的数的总个数
    javascript
    今天的排版
    论学习php的方法
    我想对所有新程序员说的一些话
    注册表单
    安卓机器人
  • 原文地址:https://www.cnblogs.com/FloraLOVERyuuji/p/10103360.html
Copyright © 2011-2022 走看看