BZOJ3993 星际战争(最大流)
2016-03-20 21:49
381 查看
显然这是一个二分图。我们假设在k时间内能够摧毁所有机器人,那么第i个激光武器总共能够削弱k∗Bik*B_i的装甲值。也就是说,∑k∗Bi≥∑Ai \sum k*B_i \geq \sum A_i。那么构建一张网络流的图,s向激光武器连边,容量为k∗Bik*B_i,激光武器向对应的机器人连边,容量为inf,机器人向t连边容量为AiA_i。决策满足单调性,二分最短时间k;最后判断是否满流(我也不知道为什么判断maxflow是否大于∑Ai\sum A_i就WA了,估计精度被卡)。
#include<cstdio> #include<cstring> #include<vector> #define MAXN 3010 #define INF 1e10 #define eps 1e-7 using namespace std; inline double Min(double a,double b) {return a<b?a:b;} struct E { int v,op; double w; E(){} E(int a,double b,int c) {v = a; w = b; op = c;} }; vector<E> g[MAXN]; int d[MAXN],vd[MAXN],n,m,s,t; int a[MAXN],b[MAXN]; double sum,flow; void add(int u,int v,double w) { g[u].push_back(E(v,w,g[v].size())); g[v].push_back(E(u,0.0,g[u].size()-1)); } double aug(int i,double augco) { int j,sz = g[i].size(),mind = t-1; double delta,augc = augco; if(i == t) return augco; for(j = 0; j < sz; j++) { int v = g[i][j].v; if(g[i][j].w > 0) { if(d[i] == d[v]+1) { delta = Min(augc,g[i][j].w); delta = aug(v,delta); g[i][j].w -= delta; g[v][g[i][j].op].w += delta; augc -= delta; if(d[s] >= t) return augco-augc; if(augc <= 0) break; } if(d[v] < mind) mind = d[v]; } } if(augc == augco) { vd[d[i]]--; if(!vd[d[i]]) d[s] = t; d[i] = mind+1; vd[d[i]]++; } return augco-augc; } void sap() { flow = 0; memset(d,0,sizeof d); memset(vd,0,sizeof vd); vd[0] = t; while(d[s] < t) flow += aug(s,(double)INF); } bool check(double k) { int i = 0,j,sz = g[s].size(),v; for(i = 0; i < sz; i++) { v = g[s][i].v; g[s][i].w = (double)b[v-n]*k; g[v][g[s][i].op].w = 0.0; } for(i = 1; i <= n; i++) { sz = g[i].size(); for(j = 0; j < sz; j++) { v = g[i][j].v; if(v == t) g[i][j].w = (double)a[i],g[t][g[i][j].op].w = 0.0; else g[i][j].w = 0.0,g[v][g[i][j].op].w = (double)INF; } } sap(); for(i = 1; i <= n; i++) { sz = g[i].size(); for(j = 0; j < sz; j++) { v = g[i][j].v; if(v != t) continue; if(g[i][j].w > eps) return false; } } return true; } int main() { scanf("%d%d",&n,&m); s = n+m+1,t = s+1; for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); add(i,t,(double)a[i]); //sum += (double)a[i]; } for(int i = 1; i <= m; i++) { scanf("%d",&b[i]); add(s,i+n,(double)b[i]); } int x; for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) { scanf("%d",&x); if(x) add(i+n,j,(double)INF); } double l = 0,r = 5e6,mid,ans; while(r-l>eps) { mid = (l+r)/2; if(check(mid)) r = mid,ans = mid; else l = mid; } printf("%lf\n",(l+r)/2); }
相关文章推荐
- javaweb学习之Http协议
- Http协议
- Hibernate逍遥游记-第13章 映射实体关联关系-003单向多对多
- 利息的后续要求
- 主要几个浏览器的内核是什么
- UVA 10895——Matrix Transpose
- 选择排序
- Java开发流程自动化(svn+maven+nexus+jenkins) --自动编译,持续集成,测试,打包,发布/部署
- [Chromium中文文档]多进程资源加载
- android中Martix中的数学原理
- Java客户端C++服务端Socket交互通信
- Hibernate Tools for Eclipse的使用
- 从头到尾彻底解析Hash表算法
- SQL SERVER-identity | @@identity | scope_identity
- 博客园环境测试
- 利用Spring AOP 更新memcached 缓存策略的实现(一)
- Lucene 加权的值
- Spark读取数据库(Mysql)的四种方式讲解
- hdoj1060Leftmost Digit
- Hibernate Tools-代码生成