[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] 地震的主要内容,如果未能解决你的问题,请参考以下文章
[USACO09JAN]地震造成的破坏Earthquake Damage
洛谷P2932 [USACO09JAN]地震造成的破坏Earthquake Damage
洛谷2944 [USACO09MAR]地震损失2Earthquake Damage 2