您的位置:首页 > 其它

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 太弱,只会做水题。

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: