zoukankan      html  css  js  c++  java
  • Luogu 4951 [USACO 2001 OPEN]地震

    水个博客玩。

    $01$分数规划。

    题目要求$frac{F - sum_{i = 1}^{n}C_i}{T_i}$最大,设$frac{F - sum_{i}C_i}{T_i} geq e$,移项一下可以得到$F - sum_{i }(e * T_i + C_i) geq 0$。

    那么在外层二分一个$e$,然后把所有边的权值设成$e * T_i + C_i$做最小生成树,假设这样子生成树的权值为$res$,如果$F - res > 0$ 那么说明答案还可以更大,否则更小。

    时间复杂度$O(mlogmlogn(MaxInt))$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef double db;
    
    const int N = 405;
    const int M = 10005;
    const db eps = 1e-6;
    const db inf = 1e10;
    
    int n, m, ufs[N];
    ll cur;
    
    struct Pathway {
        int u, v;
        ll c, t;
        db val;
        
        friend bool operator < (const Pathway &x, const Pathway &y) {
            return x.val < y.val;
        }
        
    } pat[M];
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    int find(int x) {
        return x == ufs[x] ? x : ufs[x] = find(ufs[x]);
    }
    
    inline bool chk(db mid) {
        for(int i = 1; i <= m; i++)
            pat[i].val = mid * pat[i].t + 1.0 * pat[i].c;
            
        sort(pat + 1, pat + 1 + m);
        for(int i = 1; i <= n; i++) ufs[i] = i;
        int cnt = 0; db res = 0;
        for(int i = 1; i <= m; i++) {
            int u = find(pat[i].u), v = find(pat[i].v);
            if(u == v) continue;
            ufs[u] = v;
            ++cnt;
            res += pat[i].val;
            if(cnt >= n - 1) break;
        }
        
        return (1.0 * cur - res) > 0;
    }
    
    int main() {
        read(n), read(m), read(cur);
        for(int i = 1; i <= m; i++) 
            read(pat[i].u), read(pat[i].v), read(pat[i].c), read(pat[i].t);
        
        db ln = 0.0, rn = inf, mid, res = 0.0;
        for(; ln + eps <= rn; ) {
            mid = (ln + rn) * 0.5;
            if(chk(mid)) ln = mid, res = mid;
            else rn = mid;
        }
        
        printf("%.4f
    ", res);
        return 0;
    }
    View Code
  • 相关阅读:
    图像、视频等文件类型(拓展名)
    图像、视频等文件类型(拓展名)
    Mstar 编译器的搭建
    microsoft windows network 不允许一个用户使用一个以上用户名与服务器或共享资源的多重连接
    Ubuntu 14.04报“leaking memory”错误
    linux下创建与删除用户详细步骤 ***
    GX 编译器 的搭建
    VMware网络模式介绍
    ubuntu 源更新(sources.list)
    目录的执行权限
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9894543.html
Copyright © 2011-2022 走看看