Escape(状态压缩+最大流,好题)
Escape
http://acm.hdu.edu.cn/showproblem.php?pid=3605
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 13201 Accepted Submission(s): 3329
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000
If you can output YES, otherwise output NO.
在TLE n次之后,才反应过来,n太大了。。。
百度之后才知道,需要用类似状态压缩的方法
因为m<=10,所以状态数量只有1000左右,把每个会遇到的状态数的数量记录下来,从源点到左边的点拉容量为a[i]的边,左边的点到右边的点拉容量为INF的边,右边的点到汇点拉容量为ci的边
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#define maxn 200005
#define MAXN 200005
#define mem(a,b) memset(a,b,sizeof(a))
const int N=;
const int M=;
const int INF=0x3f3f3f3f;
using namespace std;
int n;
struct Edge{
int v,next;
int cap,flow;
}edge[MAXN*];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
int cnt=;//实际存储总边数
void isap_init()
{
cnt=;
memset(pre,-,sizeof(pre));
}
void isap_add(int u,int v,int w)//加边
{
edge[cnt].v=v;
edge[cnt].cap=w;
edge[cnt].flow=;
edge[cnt].next=pre[u];
pre[u]=cnt++;
}
void add(int u,int v,int w){
isap_add(u,v,w);
isap_add(v,u,);
}
bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
{
memset(dep,-,sizeof(dep));
memset(gap,,sizeof(gap));
gap[]=;
dep[t]=;
queue<int>q;
while(!q.empty())
q.pop();
q.push(t);//从汇点开始反向建层次图
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=pre[u];i!=-;i=edge[i].next)
{
int v=edge[i].v;
if(dep[v]==-&&edge[i^].cap>edge[i^].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
{
dep[v]=dep[u]+;
gap[dep[v]]++;
q.push(v);
//if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
//break;
}
}
}
return dep[s]!=-;
}
int isap(int s,int t)
{
if(!bfs(s,t))
return ;
memcpy(cur,pre,sizeof(pre));
//for(int i=1;i<=n;i++)
//cout<<"cur "<<cur[i]<<endl;
int u=s;
path[u]=-;
int ans=;
while(dep[s]<n)//迭代寻找增广路,n为节点数
{
if(u==t)
{
int f=INF;
for(int i=path[u];i!=-;i=path[edge[i^].v])//修改找到的增广路
f=min(f,edge[i].cap-edge[i].flow);
for(int i=path[u];i!=-;i=path[edge[i^].v])
{
edge[i].flow+=f;
edge[i^].flow-=f;
}
ans+=f;
u=s;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i!=-;i=edge[i].next)
{
v=edge[i].v;
if(dep[v]+==dep[u]&&edge[i].cap-edge[i].flow)
{
cur[u]=path[v]=i;//当前弧优化
flag=true;
break;
}
}
if(flag)
{
u=v;
continue;
}
int x=n;
if(!(--gap[dep[u]]))return ans;//gap优化
for(int i=pre[u];i!=-;i=edge[i].next)
{
if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
{
x=dep[edge[i].v];
cur[u]=i;//常数优化
}
}
dep[u]=x+;
gap[dep[u]]++;
if(u!=s)//当前点没有增广路则后退一个点
u=edge[path[u]^].v;
}
return ans;
} int a[maxn]; int main(){
int m,s,t;
while(~scanf("%d %d",&n,&m)){
int b,c;
memset(a,,sizeof(a));
int Max=;
isap_init();
for(int i=;i<=n;i++){
int tmp=;
for(int j=;j<=m;j++){
scanf("%d",&c);
tmp=(tmp<<)|c;
}
if(Max<tmp) Max=tmp;
a[tmp]++;
}
s=,t=Max+m+;
for(int i=;i<=m;i++){
scanf("%d",&c);
add(Max+i,t,c);
}
for(int i=;i<=Max;i++){
if(a[i]>){
add(s,i,a[i]);
int k=m,p=i;
while(k&&p){
int tmp=p%;
p/=;
if(tmp>) add(i,Max+k,INF);
k--;
}
}
}
int tmp=n;
n=Max+m+;
int ans=isap(s,t);
if(ans==tmp) puts("YES");
else puts("NO");
}
}
Escape(状态压缩+最大流,好题)的更多相关文章
- POJ 2441 Arrange the Bulls 状态压缩递推简单题 (状态压缩DP)
推荐网址,下面是别人的解题报告: http://www.cnblogs.com/chasetheexcellence/archive/2012/04/16/poj2441.html 里面有状态压缩论文 ...
- HDU3605:Escape(状态压缩+最大流)
Escape Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- HDU 3605 Escape(状态压缩+最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意: 有n个人和m个星球,每个人可以去某些星球和不可以去某些星球,并且每个星球有最大居住人数,判断是否所 ...
- HDU3605(KB11-M 状态压缩+最大流)
Escape Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Subm ...
- Codeforces 1383F - Special Edges(状态压缩+最大流)
Codeforces 题目传送门 & 洛谷题目传送门 首先暴力显然是不行的,如果你暴力最大流过了我请你吃糖 注意到本题的 \(k\) 很小,考虑以此为突破口解题.根据最大流等于最小割定理,点 ...
- 状态压缩---区间dp第一题
标签: ACM 题目 Gappu has a very busy weekend ahead of him. Because, next weekend is Halloween, and he is ...
- Victor and World(spfa+状态压缩dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/ ...
- HDU 3001(状态压缩dp)
状态压缩dp的第一题! 题意:Mr ACMer想要进行一次旅行,他决定访问n座城市.Mr ACMer 可以从任意城市出发,必须访问所有的城市至少一次,并且任何一个城市访问的次数不能超过2次.n座城市间 ...
- 【BZOJ2734】【HNOI2012】集合选数(状态压缩,动态规划)
[BZOJ2734][HNOI2012]集合选数(状态压缩,动态规划) 题面 Description <集合论与图论>这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所 ...
随机推荐
- 学习笔记之FluentAssertions
dotnet/src/MoqSample at master · haotang923/dotnet · GitHub https://github.com/htanghtang/dotnet/tre ...
- 制作jQuery文字提示插件
(functions($){ $.fn.colorTip=function(settings){ var defaultSettings={ color:'yellow', timeout:500 } ...
- seaborn可视化特征的相关性
import seaborn as sn sn.heatmap(trainX.corr(),vmax=1,square=True)
- Java 导入证书
在这个目录下: ${JAVA_HOME}\jre\lib\security 执行 keytool -importcert -trustcacerts -file yourcerfile.pem -al ...
- mysql监控以及调优
mysql 优点: 简单易用,成本低,易扩展,复制功能领先 mysql的生命周期: Mysql服务器监听3306端口>验证访问用户>创建mysql线程>检查内存(Qcache)> ...
- VC字符串转换常用函数
最近在做一些关于VC的ActiveX小插件,经常会遇到字符串处理的问题,狂查CSDN和MSDN,结果并不理想.先说明一下,相关处理函数在VC++6.00测试通过.也许很多人不能理解,现在都什么年代了, ...
- xrange
range返回一个列表 xrange反会xrange这个类的实例,每次遍历返回一个值.比range的执行效率要高 在python3中range = xrange range(1,10,2) - ...
- python装饰器(docorator)详解
引言: 装饰器是python面向对象编程三大器之一,另外两个迭代器.生成器只是我现在还没有遇到必须使用的场景,等确实需要用到的时候,在补充资料:装饰器在某些场景真的是必要的,比如定义了一个类或者一个函 ...
- windows2012任务计划不执行
1.Windows Server 2008 计划任务在哪里配置? 2.Windows Server 2008 可以配置每分钟或是每小时执行我的任务吗? 答案是:可以! 首先Windows Server ...
- 60. vbe6ext.olb 不能被加载
找到C:\Program Files\Common Files\Microsoft Shared\VBA\路径: 把VBA6文件夹下面的VBE6.DLL改为:VBE7.DLL (如果没有VBA6文件夹 ...