思路:
因为每个人对于m个星球都只能是1或0,所以一共
2m
种状态。又因为m最大为10,1024中状态远远小于100000个点,所以我们按照状态缩点就好。
建边的话,s连每个状态的点,容量为点的个数。星球的编号连t;
中间的边直接容量直接为inf就好。
直接看代码:
ps:
- 听说曾将是1s而且数据贼弱。
- 所以加强了数据是很自然的吧
- 所以网上的ac代码都t了。。。
- 所以很自然的加到了2s。
- 然而意外的感觉卡的很紧啊,我的极致优化的isap还跑了1700+ms。
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<map>
#define inf 0x3f3f3f3f
typedef long long int lli;
using namespace std;
const lli maxn = 200000;
struct edge{
lli to,v,next;
}ed[maxn+2000000];
lli d[maxn],cur[maxn],pre[maxn],gap[maxn],q[maxn+2000],cnte,head[maxn];
void ae(lli x, lli y, lli v) {
ed[cnte].to = y;
ed[cnte].v = v;
ed[cnte].next = head[x];
head[x] = cnte++;
ed[cnte].to = x;
ed[cnte].v = 0;
ed[cnte].next = head[y];
head[y] = cnte++;
}
void rbfs (lli s,lli t) {
lli fi,se;
memset(gap,0,sizeof(gap));
memset(d,-1,sizeof(d));
d[t] = 0;
gap[0] = 1;
fi = se = 0;
q[se++] = t;
while (fi != se) {
lli u = q[fi++];
for (lli i=head[u];~i;i=ed[i].next) {
lli v = ed[i].to;
if (~d[v]) continue;
d[v] = d[u] + 1;
q[se++] = v;
gap[d[v]]++;
}
}
}
lli isap(lli s,lli t){
memcpy(cur,head,sizeof(head));
rbfs (s,t);
lli flow = 0, u = pre[s]=s,i;
while(d[t] < t+1) {
if(u==t) {
lli f = inf,neck;
for(i= s;i != t;i = ed[cur[i]].to){
if(f > ed[cur[i]].v){
f = ed[cur[i]].v;
neck = i;
}
}
for(i = s;i != t;i = ed[cur[i]].to){
ed[cur[i]].v -= f;
ed[cur[i]^1].v += f;
}
flow += f;
u = neck;
}
for(i = cur[u];~i;i=ed[i].next) if(d[ed[i].to]+1 == d[u] && ed[i].v) break;
if(~i) {
cur[u] = i;
pre[ed[i].to] = u;
u = ed[i].to;
}
else{//否则回退,重新找增广路
if(gap[d[u]] == 0 || 0 == (--gap[d[u]])) break;//GAP间隙优化,如果出现断层,可以知道一定不会再有增广路了
lli mind = t+1;
for(i = head[u];~i;i = ed[i].next){
if(ed[i].v && mind > d[ed[i].to]){
cur[u] = i;
mind = d[ed[i].to];
}
}
d[u] = mind + 1;
gap[d[u]]++;
u = pre[u];
}
}
return flow;
}
void ini(){
memset(head,-1,sizeof(head));cnte = 0;
}
int cnt[2000];
int main(){
int n,f,d,m,v,cas;
while(~scanf("%d%d",&n,&m)){
ini();
int len = (2<<m);
memset(cnt,0,sizeof(cnt));
int s=0,t = len+m+1;
for(int i = 1;i <= n;i++){
int temp = 0;
for(int j = 1;j <= m;j++){
scanf("%d",&v);
temp = temp*2 + v;
}
cnt[temp]++;
}
for(int i = 1;i <= len;i++){
int temp = i,j = m;
while(temp){
if(temp&1){
ae(i,len+j,inf);
}
j--;
temp >>= 1;
}
}
for(int i = 1;i <= m;i++){
scanf("%d",&v);
ae(len+i,t,v);
}
for(int i = 1;i <= len;i++){
ae(s,i,cnt[i]);
}
if(isap(s,t) == n){
puts("YES");
}
else
puts("NO");
}
return 0;
}