HDU3605(KB11-M 状态压缩+最大流)

Escape

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 10920    Accepted Submission(s): 2630

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

2010 ACM-ICPC Multi-University Training Contest(17)——Host by ZSTU

由于n很大,直接建图会T,但是m很小,因此根据一个人在能否在m个星球上生存的状态,可以压缩为一个m位二进制数。最多有2^10种状态。

源点向每一种状态连边,容量为该状态的人数。

每个状态向该状态下能够生存的星球连边,容量为该状态的人数。

每个星球向汇点连边,容量为星球最多能承受的人数。

  1 //2017-08-24
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 #include <queue>
  7
  8 using namespace std;
  9
 10 const int N = 110000;
 11 const int M = 5100100;
 12 const int INF = 0x3f3f3f3f;
 13 int head[N], tot;
 14 struct Edge{
 15     int next, to, w;
 16 }edge[M];
 17
 18 void add_edge(int u, int v, int w){
 19     edge[tot].w = w;
 20     edge[tot].to = v;
 21     edge[tot].next = head[u];
 22     head[u] = tot++;
 23
 24     edge[tot].w = 0;
 25     edge[tot].to = u;
 26     edge[tot].next = head[v];
 27     head[v] = tot++;
 28 }
 29
 30 struct Dinic{
 31     int level[N], S, T;
 32     void init(int _S, int _T){
 33         S = _S;
 34         T = _T;
 35         tot = 0;
 36         memset(head, -1, sizeof(head));
 37     }
 38     bool bfs(){
 39         queue<int> que;
 40         memset(level, -1, sizeof(level));
 41         level[S] = 0;
 42         que.push(S);
 43         while(!que.empty()){
 44             int u = que.front();
 45             que.pop();
 46             for(int i = head[u]; i != -1; i = edge[i].next){
 47                 int v = edge[i].to;
 48                 int w = edge[i].w;
 49                 if(level[v] == -1 && w > 0){
 50                     level[v] = level[u]+1;
 51                     que.push(v);
 52                 }
 53             }
 54         }
 55         return level[T] != -1;
 56     }
 57     int dfs(int u, int flow){
 58         if(u == T)return flow;
 59         int ans = 0, fw;
 60         for(int i = head[u]; i != -1; i = edge[i].next){
 61             int v = edge[i].to, w = edge[i].w;
 62             if(!w || level[v] != level[u]+1)
 63                   continue;
 64             fw = dfs(v, min(flow-ans, w));
 65             ans += fw;
 66             edge[i].w -= fw;
 67             edge[i^1].w += fw;
 68             if(ans == flow)return ans;
 69         }
 70         if(ans == 0)level[u] = -1;
 71         return ans;
 72     }
 73     int maxflow(){
 74         int flow = 0, f;
 75         while(bfs())
 76               while((f = dfs(S, INF)) > 0)
 77                 flow += f;
 78         return flow;
 79     }
 80 }dinic;
 81
 82 char str[N];
 83 int status[1<<12];//status[S]表示状态为S的人数,例如S=1010,表示可以在2号和4号星球上生存(从低位标号)
 84
 85 int main()
 86 {
 87     std::ios::sync_with_stdio(false);
 88     //freopen("inputM.txt", "r", stdin);
 89     int n, m;
 90     while(cin>>n>>m){
 91         int s = 0, t = n+m+1;
 92         dinic.init(s, t);
 93         int w;
 94         memset(status, 0, sizeof(status));
 95         for(int i = 1; i <= n; i++){
 96             int tmp = 0;
 97             for(int j = 1; j <= m; j++){
 98                 tmp <<= 1;
 99                 cin>>w;
100                 tmp |= w;
101             }
102             status[tmp]++;
103         }
104         for(int i = 1; i <= (1<<10); i++){
105             if(status[i]){
106                 add_edge(s, i, status[i]);
107                 for(int j = 1; j <= m; j++){
108                     if(i & (1<<(j-1)))
109                           add_edge(i, n+j, status[i]);
110                 }
111             }
112         }
113         int sum = 0;
114         for(int i = 1; i <= m; i++){
115             cin>>w;
116             sum += w;
117             add_edge(n+i, t, w);
118         }
119         if(sum < n){
120             cout<<"NO"<<endl;
121             continue;
122         }
123         if(dinic.maxflow() == n)cout<<"YES"<<endl;
124         else cout<<"NO"<<endl;
125     }
126     return 0;
127 }
时间: 2024-12-22 23:26:16

HDU3605(KB11-M 状态压缩+最大流)的相关文章

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 Problem Description 2012 If this is the end of the wor

HDU 3605 Escape(状态压缩+最大流)

http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意: 有n个人和m个星球,每个人可以去某些星球和不可以去某些星球,并且每个星球有最大居住人数,判断是否所有人都能去这m个星球之中. 思路: 这道题建图是关键,因为n的数量很大,如果直接将源点和人相连,是会超时的,因为m≤10,所以每个人的选择可以用二进制来存储,这样最多也就1<<m-1种状态,相同的就可以放在一起处理了. 1 #include<iostream> 2 #include&l

HDU 3605 —— Escape 状态压缩+最大流

原题:http://acm.hdu.edu.cn/showproblem.php?pid=3605 #include<cstdio> #include<cstring> #include<string> #include<queue> #include<cmath> #include<vector> #include<algorithm> #define inf 1e9 using namespace std; const

hdu3605(最大流+状态压缩)

传送门:Escape 题意:给出每个人适合住的星球信息和该星球能住多少人 ,第一行给出n m 代表有 n 个人 m 个星球,然后接下来n行每行m个数字 1代表适合第 i 个星球 0 代表不适合第 i 个星球,最后一行m个数表示第 i 个星球最多可以住多少个人,问是不是所有人都可以住到星球上. 分析:很裸的最大流,但刚开始直接去建图,100W级别的边MLE了,就算没MLE也会TLE的,因此需要状态压缩,m<=10,最多1024种状态,边数降成1W级别,最大流妥妥的A了. #pragma comme

软件补丁问题(状态压缩 最短路)

先状态压缩,再求费用流,但耗内存太大,改变存边方式降低内存使用. 直接求最短路即可 //http://www.cnblogs.com/IMGavin/ #include <iostream> #include <stdio.h> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <map> #include &

状态压缩DP与TSP问题

状态压缩DP DP过程中的状态不可能像背包问题一样只有整数,肯定有各种各样稀奇古怪的状态,需要不止一个变量来表示.这种情况下如果需要使用DP 就必须把状态压缩成一个数来表示,并且一个数只能对应于一种状态. 特别地,对于集合我们可以把每一个元素的选取与否对应到一个二进制位里,从而把状态压缩成一个整数,大大方便了计算和维护. 对于不是整数的情况,很多时候很难确定一个合适的递推顺序,因此使用记忆化搜索可以避免这个问题.如下面TSP问题的法一. TSP问题 一张图上有n个点,给定相应的邻接矩阵,需要求出

hdu 3605 /状态合并最大流

题意:N个人去m个星球,给出n个人可以去哪些星球的01矩阵.求是否能满足所有人都去.(n到10万,m<=10) 一看,起先一瞬间就建图,准备秒了,人向星球连边,直接最大流判断是否为n,提交超时...是啊,10W*10=100W条边,铁定超时.. 后来经牛提示:注意,m<10!  人的可以去星球,一共最多有10个,那只有 2^10次种情况,就是说x部与Y部连线情况很多点是一样的(所给的01矩阵,最多10W行,10列,必然有很多行是一样的).所以X部只留1024个点,这些点中,点i含j个人的状态,

FZU1892接水管游戏-BFS加上简单的状态压缩和位运算处理

原题地址:http://acm.fzu.edu.cn/problem.php?pid=1892 Problem 1892 接水管游戏 Accept: 108    Submit: 498 Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 接水管游戏的规则如下: 1.在N*N大小的方格上有两个特别的水管,分别为进水口和出水口: 2.有7种1*1大小的水管需要放在这N*N大小的方格内,使得水流能够从进水口经过这些

胜利大逃亡(续)(状态压缩bfs)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7357    Accepted Submission(s): 2552 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带