BZOJ 3993 [SDOI 2015] 星际战争 解题报告
2015-04-15 21:14
274 查看
首先我们可以二分答案。
假设当前二分出来的答案是 $Ans$ ,那么我们考虑用网络流检验:
设武器为 $X$,第 $i$ 个武器的攻击力为 $B_i$;
设机器人为 $Y$,第 $i$ 个机器人的装甲为 $A_i$;
设 $Map[i][j]$ 表示第 $i$ 个机器人是否能攻击第 $j$ 号机器人。
设源为 $S$,汇为 $T$,现在考虑连边:
$S\rightarrow X_i$,容量为 $Ans * B_i$;
$Y_i\rightarrow T$,容量为 $A_i$;
$\forall (i,j),Map[i][j]=1:X_i\rightarrow Y_j$,容量为 $\infty$
然后跑网络流,假设最大流为 $M$,那么看是否有:$M=\sum A_i$。
如果是,那么说明当前答案是满足的,更新上界,否则更新下界。
毕竟 Gromah 太弱,只会做水题。
3993_Gromah
假设当前二分出来的答案是 $Ans$ ,那么我们考虑用网络流检验:
设武器为 $X$,第 $i$ 个武器的攻击力为 $B_i$;
设机器人为 $Y$,第 $i$ 个机器人的装甲为 $A_i$;
设 $Map[i][j]$ 表示第 $i$ 个机器人是否能攻击第 $j$ 号机器人。
设源为 $S$,汇为 $T$,现在考虑连边:
$S\rightarrow X_i$,容量为 $Ans * B_i$;
$Y_i\rightarrow T$,容量为 $A_i$;
$\forall (i,j),Map[i][j]=1:X_i\rightarrow Y_j$,容量为 $\infty$
然后跑网络流,假设最大流为 $M$,那么看是否有:$M=\sum A_i$。
如果是,那么说明当前答案是满足的,更新上界,否则更新下界。
毕竟 Gromah 太弱,只会做水题。
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long double LD; #define N 50 + 5 #define M 100000 + 5 #define INF 1e9 #define eps 1e-9 int n, m, S, T, sum, tot; int A , B ; int Head[N << 1], q[N << 1], Dfn[N << 1]; bool Map ; LD l = 0.0, r; struct Edge { int next, node; LD flow; }h[M]; inline void addedge(int u, int v, LD fl) { h[++ tot].next = Head[u], Head[u] = tot; h[tot].node = v, h[tot].flow = fl; h[++ tot].next = Head[v], Head[v] = tot; h[tot].node = u, h[tot].flow = 0; } inline bool BFS() { for (int i = S; i <= T; i ++) Dfn[i] = 0; int l = 1, r = 1; q[1] = S, Dfn[S] = 1; while (l <= r) { int z = q[l ++]; for (int i = Head[z]; i; i = h[i].next) { int d = h[i].node; LD p = h[i].flow; if (p < eps || Dfn[d]) continue ; Dfn[d] = Dfn[z] + 1; q[++ r] = d; if (d == T) return 1; } } return 0; } inline LD dinic(int z, LD inflow) { if (z == T || inflow < eps) return inflow; LD ret = inflow, flow; for (int i = Head[z]; i; i = h[i].next) { int d = h[i].node; LD p = h[i].flow; if (Dfn[d] != Dfn[z] + 1) continue ; flow = dinic(d, min(p, ret)); ret -= flow; h[i].flow -= flow, h[i ^ 1].flow += flow; if (ret < eps) return inflow; } if (fabs(inflow - ret) < eps) Dfn[z] = -1; return inflow - ret; } inline bool Judge(LD k) { tot = 1; for (int i = S; i <= T; i ++) Head[i] = 0; for (int i = 1; i <= m; i ++) addedge(S, i, k * B[i]); for (int i = 1; i <= n; i ++) addedge(i + m, T, A[i]); for (int i = 1; i <= m; i ++) for (int j = 1; j <= n; j ++) if (Map[i][j]) addedge(i, j + m, INF); LD res = 0.0; while (BFS()) res += dinic(S, INF); return fabs(res - sum) < eps; } int main() { #ifndef ONLINE_JUDGE freopen("3993.in", "r", stdin); freopen("3993.out", "w", stdout); #endif scanf("%d%d", &n, &m); S = 0, T = n + m + 1; for (int i = 1; i <= n; i ++) { scanf("%d", A + i); r += A[i]; sum += A[i]; } for (int i = 1; i <= m; i ++) scanf("%d", B + i); for (int i = 1; i <= m; i ++) for (int j = 1; j <= n; j ++) scanf("%d", Map[i] + j); while (l + 1e-4 < r) { LD mid = (l + r) / 2; if (Judge(mid)) r = mid; else l = mid; } printf("%.4lf\n", (double) l); #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif return 0; }
3993_Gromah
相关文章推荐
- BZOJ 3993 [SDOI 2015] 网络流+二分答案 解题报告
- bzoj3993 [SDOI2015]星际战争(double网络流)
- 【BZOJ3993】星际战争(SDOI2015)-二分答案+最大流
- bzoj 3993: [Sdoi2015]星际战争
- [BZOJ3993][SDOI2015]星际战争(二分答案+最大流)
- BZOJ 3993 [SDOI2015]星际战争
- BZOJ 3993: [SDOI2015]星际战争 [二分答案 二分图]
- [BZOJ3993][SDOI2015]星际战争(二分+最大流)
- 【BZOJ3993】【SDOI2015】星际战争(网络流+二分)
- bzoj千题计划131:bzoj3993: [SDOI2015]星际战争
- BZOJ_3993_[SDOI2015]星际战争_二分+网络流
- 【BZOJ 3993】【SDOI 2015】星际战争
- 【BZOJ 3993】 [SDOI2015]星际战争
- [SDOI2015][bzoj3993] 星际战争 [二分+最大流]
- BZOJ 3992 [SDOI 2015] 序列统计 解题报告
- BZOJ 3993 Sdoi2015 星际战争 二分答案+最大流
- bzoj3993 [SDOI2015]星际战争 二分答案+网络流检验
- 【bzoj3993】[SDOI2015]星际战争 二分+最大流
- BZOJ 3993: [SDOI2015]星际战争
- BZOJ 3993 SDOI2015 星际战争