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}的所 ...
随机推荐
- 接口测试3-2csv格式
csv文件数据 IntellJ IDEA打开终端:view-tool windows-terminal,可以在终端中查看文件路径 阿里 马云 京东 刘强东 京东 马化腾 #java //读取csv文件 ...
- Linux设置history命令显示时间
效果如图: 设置方法如下: vim /etc/bashrc #command-->history set HISTFILESIZE=2000 #保存命令的总数默认总数为1000 HISTSIZE ...
- vs2013错误解决方法
1.cannot determine the location of the vs common tools folder 打开"VS2013开发人员命令提示后",上面提示&quo ...
- Python XML解析
什么是XML? XML 指可扩展标记语言(eXtensible Markup Language). 你可以通过本站学习XML教程 XML 被设计用来传输和存储数据. XML是一套定义语义标记的规则,这 ...
- Java面向对象技术
问题及答案来源自<Java程序员面试笔试宝典>第四章 Java基础知识 4.2面向对象技术 1.面向对象与面向过程有什么区别? 看下面一个实例即可: 面向过程就是分析出解决问题所需要的步骤 ...
- CSS层叠样式
为了让网页元素的样式更加丰富,也为了让网页的内容和样式能拆分开,CSS由此思想而诞生,CSS是 Cascading Style Sheets 的首字母缩写,意思是层叠样式表.有了CSS,html中大部 ...
- openStack虚拟机error 错误状态基于差异镜像+基镜像做恢复
- 传统三层架构与DDD分层架构
参考 https://www.cnblogs.com/sandyliu1999/p/4969445.html
- PHP 程序员学数据结构与算法之《栈》
“要成高手,必练此功”. 要成为优秀的程序员,数据结构和算法是必修的内容.而现在的Web程序员使用传统算法和数据结构都比较少,因为很多算法都是包装好的,不用我们去操心具体的实现细节,如PHP的取栈 ...
- Jenkins + testNg + maven 项目持续集成
搞了一整天,梳理下关键点: 1.项目的pom.xml要配置插件,同时指定testng.xml文件的位置.就被这个卡了好久 <properties> <maven-surefire-p ...