[BZOJ3993][SDOI2015]星际战争(二分答案+最大流)
2017-11-21 18:30
471 查看
先二分时间,记当前判断的时间为time。
建立源点和汇点,建图为:
1、∀1≤i≤M,由源点向第i个激光武器建一条容量为time∗Bi的边。
2、∀1≤i≤N,由第i个巨型机器人向汇点建一条容量为Ai的边。
3、∀1≤i≤M,1≤j≤N,如果第i个激光武器可以攻击第j个机器人,那么由第i个激光武器向第j个机器人连一条容量为∞的边。
跑一遍最大流,如果最大流等于∑Ni=1Ai,那么在time或比time更短的时间内,可以摧毁所有的机器人。
注意精度。
代码:
建立源点和汇点,建图为:
1、∀1≤i≤M,由源点向第i个激光武器建一条容量为time∗Bi的边。
2、∀1≤i≤N,由第i个巨型机器人向汇点建一条容量为Ai的边。
3、∀1≤i≤M,1≤j≤N,如果第i个激光武器可以攻击第j个机器人,那么由第i个激光武器向第j个机器人连一条容量为∞的边。
跑一遍最大流,如果最大流等于∑Ni=1Ai,那么在time或比time更短的时间内,可以摧毁所有的机器人。
注意精度。
代码:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const double eps = 1e-9, INF = 1e12; const int M = 55, N = 2e5 + 5; int n, m, a[M], b[M], ecnt = 1, nxt , adj , go , lev , len, que , cur , S, T, g[M][M], sm; double cap , Cap ; void add_edge(int u, int v, double w) { nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v; cap[ecnt] = w; nxt[++ecnt] = adj[v]; adj[v] = ecnt; go[ecnt] = u; cap[ecnt] = 0; } bool bfs() { int i; for (i = S; i <= T; i++) lev[i] = -1, cur[i] = adj[i]; que[len = 1] = S; lev[S] = 0; for (i = 1; i <= len; i++) { int u = que[i]; for (int e = adj[u], v; e; e = nxt[e]) if (cap[e] > eps && lev[v = go[e]] == -1) { que[++len] = v; lev[v] = lev[u] + 1; if (v == T) return 1; } } return 0; } double dinic(int u, double flow) { if (u == T) return flow; double res = 0, d = 0; for (int &e = cur[u], v; e; e = nxt[e]) if (cap[e] > eps && lev[u] < lev[v = go[e]]) { d = dinic(v, min(cap[e], flow - res)); if (d > eps) { cap[e] -= d; cap[e ^ 1] += d; res += d; if (fabs(flow - res) <= eps) break; } } if (fabs(flow - res) > eps) lev[u] = -1; return res; } double solve() { double ans = 0; while (bfs()) ans += dinic(S, INF); return ans; } void build(double tm) { int i; for (i = 2; i <= ecnt; i++) cap[i] = Cap[i]; for (i = 2; i <= (m << 1) + 1; i += 2) cap[i] = tm * b[i >> 1]; } double SOLVE() { double l = 0, r = 1e9, mid = (l + r) / 2; while (r - l >= eps) { build(mid); if (1.0 * sm - solve() < eps) r = mid; else l = mid; mid = (l + r) / 2; } return mid; } inline int read() { int res = 0; bool bo = 0; char c; while (((c = getchar()) < '0' || c > '9') && c != '-'); if (c == '-') bo = 1; else res = c - 48; while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48); return bo ? ~res + 1 : res; } int main() { int i, j; n = read(); m = read(); for (i = 1; i <= n; i++) a[i] = read(), sm += a[i]; for (i = 1; i <= m; i++) b[i] = read(); for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) g[i][j] = read(); S = 1; T = n + m + 2; for (i = 2; i <= m + 1; i++) add_edge(S, i, 0); for (i = m + 2; i < T; i++) add_edge(i, T, 1.0 * a[i - m - 1]); for (i = 2; i <= m + 1; i++) for (j = m + 2; j < T; j++) if (g[i - 1][j - m - 1]) add_edge(i, j, INF); for (i = 2; i <= ecnt; i++) Cap[i] = cap[i]; printf("%.6lf\n", SOLVE()); return 0; }
相关文章推荐
- 【BZOJ3993】星际战争(SDOI2015)-二分答案+最大流
- 【二分答案】【最大流】bzoj3993 [Sdoi2015]星际战争
- BZOJ 3993 Sdoi2015 星际战争 二分答案+最大流
- bzoj 3993: [SDOI2015]星际战争 二分答案+最大流
- [BZOJ3993]-[SDOI2015]星际战争-二分答案+最大流
- BZOJ 3993: [SDOI2015]星际战争 [二分答案 二分图]
- [bzoj3993][SDOI2015]星际战争-二分+最大流
- bzoj3993 [SDOI2015]星际战争 二分答案+网络流检验
- 【bzoj3993】[SDOI2015]星际战争 二分+最大流
- 【bzoj3993】[SDOI2015]星际战争 二分+最大流
- BZOJ 3993 [SDOI2015]星际战争 | 网络流 二分答案
- 【BZOJ3993】[SDOI2015]星际战争 二分+最大流
- [BZOJ3993][SDOI2015]星际战争(二分+最大流)
- bzoj 3993: [SDOI2015]星际战争 (二分+最大流)
- bzoj 3993: [SDOI2015]星际战争 二分答案&网络流
- [SDOI2015][bzoj3993] 星际战争 [二分+最大流]
- BZOJ 3993 [SDOI2015]星际战争 二分+最大流
- BZOJ 3993 [SDOI 2015] 网络流+二分答案 解题报告
- 网络流(二分):BZOJ 3993: [SDOI2015]星际战争
- BZOJ_3993_[SDOI2015]星际战争_二分+网络流