# 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

Problem Description
2012 If this is the end of the world how to do? I do not know how. But now scientists have found that some stars, who can live, but some people do not fit to live some of the planet. Now scientists want your help, is to determine what all of people can live in these planets.

Input
More set of test data, the beginning of each data is n (1 <= n <= 100000), m (1 <= m <= 10) n indicate there n people on the earth, m representatives m planet, planet and people labels are from 0. Here are n lines, each line represents a suitable living conditions of people, each row has m digits, the ith digits is 1, said that a person is fit to live in the ith-planet, or is 0 for this person is not suitable for living in the ith planet.
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000

Output
Determine whether all people can live up to these stars
If you can output YES, otherwise output NO.

Sample Input
1 1
1
1

2 2
1 0
1 0
1 1

Sample Output
YES
NO

Source

在TLE n次之后，才反应过来，n太大了。。。

百度之后才知道，需要用类似状态压缩的方法

因为m<=10，所以状态数量只有1000左右，把每个会遇到的状态数的数量记录下来，从源点到左边的点拉容量为a[i]的边，左边的点到右边的点拉容量为INF的边，右边的点到汇点拉容量为ci的边

```  1 #include<iostream>
2 #include<cstring>
3 #include<string>
4 #include<cmath>
5 #include<cstdio>
6 #include<algorithm>
7 #include<queue>
8 #include<vector>
9 #include<set>
10 #define maxn 200005
11 #define MAXN 200005
12 #define mem(a,b) memset(a,b,sizeof(a))
13 const int N=200005;
14 const int M=200005;
15 const int INF=0x3f3f3f3f;
16 using namespace std;
17 int n;
18 struct Edge{
19     int v,next;
20     int cap,flow;
21 }edge[MAXN*20];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
22 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
23 int cnt=0;//实际存储总边数
24 void isap_init()
25 {
26     cnt=0;
27     memset(pre,-1,sizeof(pre));
28 }
29 void isap_add(int u,int v,int w)//加边
30 {
31     edge[cnt].v=v;
32     edge[cnt].cap=w;
33     edge[cnt].flow=0;
34     edge[cnt].next=pre[u];
35     pre[u]=cnt++;
36 }
37 void add(int u,int v,int w){
40 }
41 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里，但是好像是时间要长
42 {
43     memset(dep,-1,sizeof(dep));
44     memset(gap,0,sizeof(gap));
45     gap[0]=1;
46     dep[t]=0;
47     queue<int>q;
48     while(!q.empty())
49     q.pop();
50     q.push(t);//从汇点开始反向建层次图
51     while(!q.empty())
52     {
53         int u=q.front();
54         q.pop();
55         for(int i=pre[u];i!=-1;i=edge[i].next)
56         {
57             int v=edge[i].v;
58             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs，但应该判断正向弧的余量
59             {
60                 dep[v]=dep[u]+1;
61                 gap[dep[v]]++;
62                 q.push(v);
63                 //if(v==sp)//感觉这两句优化加了一般没错，但是有的题可能会错，所以还是注释出来，到时候视情况而定
64                 //break;
65             }
66         }
67     }
68     return dep[s]!=-1;
69 }
70 int isap(int s,int t)
71 {
72     if(!bfs(s,t))
73     return 0;
74     memcpy(cur,pre,sizeof(pre));
75     //for(int i=1;i<=n;i++)
76     //cout<<"cur "<<cur[i]<<endl;
77     int u=s;
78     path[u]=-1;
79     int ans=0;
80     while(dep[s]<n)//迭代寻找增广路,n为节点数
81     {
82         if(u==t)
83         {
84             int f=INF;
85             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
86                 f=min(f,edge[i].cap-edge[i].flow);
87             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
88             {
89                 edge[i].flow+=f;
90                 edge[i^1].flow-=f;
91             }
92             ans+=f;
93             u=s;
94             continue;
95         }
96         bool flag=false;
97         int v;
98         for(int i=cur[u];i!=-1;i=edge[i].next)
99         {
100             v=edge[i].v;
101             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
102             {
103                 cur[u]=path[v]=i;//当前弧优化
104                 flag=true;
105                 break;
106             }
107         }
108         if(flag)
109         {
110             u=v;
111             continue;
112         }
113         int x=n;
114         if(!(--gap[dep[u]]))return ans;//gap优化
115         for(int i=pre[u];i!=-1;i=edge[i].next)
116         {
117             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
118             {
119                 x=dep[edge[i].v];
120                 cur[u]=i;//常数优化
121             }
122         }
123         dep[u]=x+1;
124         gap[dep[u]]++;
125         if(u!=s)//当前点没有增广路则后退一个点
126         u=edge[path[u]^1].v;
127      }
128      return ans;
129 }
130
131 int a[maxn];
132
133 int main(){
134     int m,s,t;
135     while(~scanf("%d %d",&n,&m)){
136         int b,c;
137         memset(a,0,sizeof(a));
138         int Max=0;
139         isap_init();
140         for(int i=1;i<=n;i++){
141             int tmp=0;
142             for(int j=1;j<=m;j++){
143                 scanf("%d",&c);
144                 tmp=(tmp<<1)|c;
145             }
146             if(Max<tmp) Max=tmp;
147             a[tmp]++;
148         }
149         s=0,t=Max+m+1;
150         for(int i=1;i<=m;i++){
151             scanf("%d",&c);
153         }
154         for(int i=1;i<=Max;i++){
155             if(a[i]>0){
157                 int k=m,p=i;
158                 while(k&&p){
159                     int tmp=p%2;
160                     p/=2;
162                     k--;
163                 }
164             }
165         }
166         int tmp=n;
167         n=Max+m+2;
168         int ans=isap(s,t);
169         if(ans==tmp) puts("YES");
170         else puts("NO");
171     }
172 }```
View Code
• 相关阅读:
第六次实验报告
第三次实验报告
第五张循环语句总结
第二次实验报告
第一次实验报告
第一次作业
第九章 结构体与共用体
第八章 指针实验
第七章数组实验
第六章实验报告(2)
• 原文地址：https://www.cnblogs.com/Fighting-sh/p/9951520.html