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
  • 相关阅读:
    招聘.Net中高级软件研发工程师
    布局和救火
    UITableView详解(转)
    iOS开发那些事--性能优化–内存泄露问题的解决(转)
    LeeCode(PHP) 2.add-two-numbers
    LeeCode(PHP) 1.Two Sum
    PHP实现 序列帧拆分
    PHPExcel导出大量数据超时及内存错误解决方法(转)
    laravel路由 实现短连接生成及跳转(php 301重定向)
    从扑克牌中随机抽取5张牌,判断是不是一个顺子,即这5张牌是不是连续(面试题)
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9894543.html
Copyright © 2011-2022 走看看