[USACO 2001 OPEN] 地震

Posted xcysblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[USACO 2001 OPEN] 地震相关的知识,希望对你有一定的参考价值。

好像是 01 分数规划 板子

列出式子 (F - ∑Ci) / (∑Ti)

设当前二分的答案为 ans

若 ans ≤ (F - ∑Ci) / (∑Ti)
则说明 ans 可以再增大

那我们二分边界调整的条件就有了

就是当 F - (∑ans*Ti + ∑Ci) ≥ 0


 代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cstdio>
using namespace std;

const int MAXN = 405, MAXM = 10005;

struct EDGE {
    int x, y, c, t;
    double hf;
    bool operator < (const EDGE& b) const {
        return hf < b.hf;
    }
}edge[MAXM];
int n, m, f;
int fa[MAXN];

inline void clearfa() {
    for (int i = 1; i <= n; ++i) fa[i] = i;
}
int findfa(int x) {
    return ((fa[x] == x) ? (x) : (fa[x] = findfa(fa[x])));
}
inline bool link(int x, int y) {
    register int fx = findfa(x), fy = findfa(y);
    if (fx == fy) return false;
    fa[fx] = fy;
    return true;
}
inline bool chk(double mid) {
    register double ans = 0.0;
    clearfa();
    for (int i = 1; i <= m; ++i) edge[i].hf = edge[i].t * mid + edge[i].c;
    sort(edge + 1, edge + m + 1);
    for (int i = 1; i <= m; ++i) {
        if (link(edge[i].x, edge[i].y)) {
            ans += edge[i].hf;
        }
    }
    return ((ans - (double)f) <= 0.0);
}
inline void hfs(double l, double r) {
    register double mid = 0.0;
    while ((r - l) > 1e-7) {
        mid = ((l + r) / 2.0);
        if (chk(mid)) l = mid;
        else r = mid;
    }
    printf("%.4lf
", l);
}

int main() {
    scanf("%d%d%d", &n, &m, &f);
    for (int i = 1; i <= m; ++i) {
        scanf("%d%d%d%d", &edge[i].x, &edge[i].y, &edge[i].c, &edge[i].t);
    }
    hfs(0, 2000000000.0);
    return 0;
}

以上是关于[USACO 2001 OPEN] 地震的主要内容,如果未能解决你的问题,请参考以下文章

[USACO 2001 OPEN]地震

[USACO09JAN]地震造成的破坏Earthquake Damage

洛谷P2932 [USACO09JAN]地震造成的破坏Earthquake Damage

洛谷2944 [USACO09MAR]地震损失2Earthquake Damage 2

[USACO09MAR]地震损失2Earthquake Damage 2

P2944 [USACO09MAR]地震损失2Earthquake Damage 2(网络流)