BZOJ3993 [SDOI2015]星際戰爭 【二分 + 網絡流】
題目
3333年,在銀河系的某星球上,X軍團和Y軍團正在激烈地作戰。在戰鬥的某一階段,Y軍團一共派遣了N個巨型機器人進攻X軍團的陣地,其中第i個巨型機器人的裝甲值為Ai。當一個巨型機器人的裝甲值減少到0或者以下時,這個巨型機器人就被摧毀了。X軍團有M個激光武器,其中第i個激光武器每秒可以削減一個巨型機器人Bi的裝甲值。激光武器的攻擊是連續的。這種激光武器非常奇怪,一個激光武器只能攻擊一些特定的敵人。Y軍團看到自己的巨型機器人被X軍團一個一個消滅,他們急需下達更多的指令。為了這個目標,Y軍團需要知道X軍團最少需要用多長時間才能將Y軍團的所有巨型機器人摧毀。但是他們不會計算這個問題,因此向你求助。
輸入格式
第一行,兩個整數,N、M。
第二行,N個整數,A1、A2…AN。
第三行,M個整數,B1、B2…BM。
接下來的M行,每行N個整數,這些整數均為0或者1。這部分中的第i行的第j個整數為0表示第i個激光武器不可以攻擊第j個巨型機器人,為1表示第i個激光武器可以攻擊第j個巨型機器人。
輸出格式
一行,一個實數,表示X軍團要摧毀Y軍團的所有巨型機器人最少需要的時間。輸出結果與標準答案的絕對誤差不超過10-3即視為正確。
輸入樣例
2 2
3 10
4 6
0 1
1 1
輸出樣例
1.300000
提示
戰鬥開始後的前0.5秒,激光武器1攻擊2號巨型機器人,激光武器2攻擊1號巨型機器人。1號巨型機器人被完全摧毀,2號巨型機器人還剩余8的裝甲值;
接下來的0.8秒,激光武器1、2同時攻擊2號巨型機器人。2號巨型機器人被完全摧毀。
對於全部的數據,1<=N, M<=50,1<=Ai<=105,1<=Bi<=1000,輸入數據保證X軍團一定能摧毀Y軍團的所有巨型機器人
題解
明顯是網絡流建圖
S連激光武器
機器人連T容量為生命值
可以攻擊的對象之間連INF的邊
然後二分時間,乘上各個武器單位傷害賦值為S到其的邊上
跑一遍最大流看看能不能跑滿
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long int
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<‘ ‘; puts("");
#define cls(s) memset(s,0,sizeof(s))
#define eps 1e-9
using namespace std;
const int maxn = 105,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == ‘-‘) flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 2;
struct EDGE{int to,nxt; double f;}ed[maxm];
inline void build(int u,int v,double f){
ed[ne] = (EDGE){v,h[u],f}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v],0}; h[v] = ne++;
}
int d[maxn],vis[maxn],cur[maxn],S,T;
bool bfs(){
cls(d); cls(vis); vis[S] = true;
queue<int> q; q.push(S);
int u;
while (!q.empty()){
u = q.front(); q.pop();
Redge(u) if (fabs(ed[k].f) > eps && !vis[to = ed[k].to]){
d[to] = d[u] + 1; vis[to] = true;
if (to == T) return true;
q.push(to);
}
}
return vis[T];
}
double dfs(int u,double minf){
if (u == T || fabs(minf) < eps) return minf;
double f,flow = 0; int to;
if (cur[u] == -1) cur[u] = h[u];
for (int& k = cur[u]; k; k = ed[k].nxt){
if (d[to = ed[k].to] == d[u] + 1 && fabs(f = dfs(to,min(minf,ed[k].f))) >= eps){
ed[k].f -= f; ed[k ^ 1].f += f;
flow += f; minf -= f;
if (fabs(minf) < 0) break;
}
}
return flow;
}
double maxflow(){
double flow = 0;
while (bfs()){
memset(cur,-1,sizeof(cur));
flow += dfs(S,INF);
}
return flow;
}
int n,m;
double sum,a[maxn],b[maxn];
int G[maxn][maxn];
bool check(double t){
memset(h,0,sizeof(h));
ne = 2;
for (int i = 1; i <= m; i++) build(S,n + i,t * b[i]);
for (int i = 1; i <= n; i++) build(i,T,a[i]);
REP(i,m) REP(j,n) if (G[i][j]) build(n + i,j,INF);
return fabs(maxflow() - sum) < eps;
}
int main(){
n = read(); m = read(); S = 0; T = n + m + 1;
REP(i,n) sum += (a[i] = read());
REP(i,m) b[i] = read();
REP(i,m) REP(j,n) G[i][j] = read();
double l = 0,r = 5000000,mid;
while (r - l > 1e-6){
mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
printf("%.6lf\n",(l + r) / 2);
return 0;
}
BZOJ3993 [SDOI2015]星際戰爭 【二分 + 網絡流】