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
  • 相关阅读:
    java常用类库
    汇编子程序使用
    Flsk&pyecharts 动态数据可视化
    2019年全国高校计算机能力挑战赛初赛C++语言解答
    搞定vscode编写java(手把手篇)
    搞定vscode编写java
    2019年全国高校计算机能力挑战赛初赛java语言解答
    Java大数类 BigInteger
    2019年全国高校计算机能力挑战赛初赛C语言解答
    二叉搜索树BST(C语言实现可用)
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9894543.html
Copyright © 2011-2022 走看看