HDU3605 Escape(最大流)
2016-03-14 20:41
351 查看
有n个人要移居m个星球,给出每个合适的星球,每个星球最多能容纳的人数,问是否所有人都可以移居。(1≤N≤105,1≤M≤10)(1\leq N\leq 10^5,1\leq M\leq10)
一开始还以为是最大流的裸题,结果TLE,翻了翻题解才知道原因:N的范围太大,那么多条边连完就TLE了。之后,又WA了RE了T了几次终于调过。
首先要明确一点,这么多人肯定有许多人的选择是重复的,而且总方案数不超过2102^{10},根据这个,我们可以对人进行缩点,选择一样的就把数量累加起来,同理,源点连过来的边修改相应的容量,连出去的边也修改。
我用的是二进制判重缩点。
一开始还以为是最大流的裸题,结果TLE,翻了翻题解才知道原因:N的范围太大,那么多条边连完就TLE了。之后,又WA了RE了T了几次终于调过。
首先要明确一点,这么多人肯定有许多人的选择是重复的,而且总方案数不超过2102^{10},根据这个,我们可以对人进行缩点,选择一样的就把数量累加起来,同理,源点连过来的边修改相应的容量,连出去的边也修改。
我用的是二进制判重缩点。
#include<cstdio> #include<cstring> #include<vector> #define MAXN 20100 using namespace std; int d[MAXN],vd[MAXN],n,m,s,t,a,flow,cnt[MAXN]; inline int Min(int a,int b) {return a<b?a:b;} struct E { int v,w,op; E(){} E(int a,int b,int c) {v = a; w = b; op = c;} }; vector<E> g[MAXN]; int aug(int i,int augco) { int j,augc = augco,mind = t-1,delta,sz = g[i].size(); if(i == t) return augco; for(j = 0; j < sz; j++) { int v = g[i][j].v; if(g[i][j].w) { if(d[i] == d[v]+1) { delta = Min(g[i][j].w,augc); 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(augco == augc) { vd[d[i]]--; if(vd[d[i]] == 0) 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,0x3f3f3f3f); } void init() { for(int i = 1; i <= t; i++) g[i].clear(); memset(cnt,0,sizeof cnt); } int main() { while(scanf("%d%d",&n,&m) != EOF) { s = (1<<m); t = s+m+1; for(int i = 1; i <= n; i++) { int temp = 0; for(int j = 1; j <= m; j++) { scanf("%d",&a); if(a) temp |= 1<<(j-1); } cnt[temp]++;//记录选择为temp的人数 } for(int i = 1; i <= (1<<m)-1; i++) { if(cnt[i]) { g[s].push_back(E(i,cnt[i],g[i].size())); g[i].push_back(E(s,0,g[s].size()-1)); int temp = i; for(int j = 1; (1<<(j-1)) <= temp; j++) if(temp&1<<(j-1))//找到对应的星球 { g[i].push_back(E(s+j,cnt[i],g[s+j].size())); g[s+j].push_back(E(i,0,g[i].size()-1)); } } } for(int i = 1; i <= m; i++) { scanf("%d",&a); g[s+i].push_back(E(t,a,g[t].size())); g[t].push_back(E(s+i,0,g[s+1].size()-1)); } sap(); if(flow == n) printf("YES\n"); else printf("NO\n"); init(); } }
相关文章推荐
- Hdu--4255 螺旋矩阵
- 质数的蛇形填数
- 利用ArcGIS对DSM进行定量比较或精度评定
- markdown语法
- 触发器
- java注释规范
- 广度优先搜索和深度优先搜索—N皇后问题
- linux设备驱动程序注册过程详解
- Poj-3278
- javascript实现查看html网页放大图片功能
- 关于Eclipse使用OkHttp
- 项目2:本月有几天?
- 火药,X射线和青霉素的发现
- android 学习之ExpandableListView
- 局部排序
- java ee环境搭建
- LINUX下JNI封装 C++动态链接库
- AbstractQueuedSynchronizer分析
- hust 数字变化
- 解决RegexKitLite编译报错