最大流,n比較大,但是m只有10,所以對應的人的狀態最多有2^m種,因此可以對人進行歸類,那樣n的數據量就只有1024了,求最大流
g++交會超時 ,要用c++
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define MAXN 1100
#define MAXE 21000
#define INF 0x7fffffff
using namespace std;
int num[MAXN];
struct Edge{
int to,from,cap,next;
}edge[MAXE];
int head[MAXN],cnt,n,m,src,des;
int dep[MAXN],gap[MAXN];
void init(){
memset(head,-1,sizeof(head));
cnt=0;
}
void addedge(int cu,int cv,int cw){
// cout<<cu<<' '<<cv<<' '<<cw<<endl;
edge[cnt].from=cu;edge[cnt].to=cv;edge[cnt].cap=cw;edge[cnt].next=head[cu];head[cu]=cnt++;
edge[cnt].from=cv;edge[cnt].to=cu;edge[cnt].cap=0;edge[cnt].next=head[cv];head[cv]=cnt++;
}
int que[MAXN];
void BFS(){
memset(dep,-1,sizeof(dep));
memset(gap,0,sizeof(gap));
gap[0]=1;
int L=0,R=0;
dep[des]=0;
que[R++]=des;
int u,v;
while(L!=R){
u=que[L++];
L=L%MAXN;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].to;
if(edge[i^1].cap==0||dep[v]!=-1)
continue;
que[R++]=v;
R=R%MAXN;
++gap[dep[v]=dep[u]+1];
}
}
}
int cur[MAXN],stack[MAXN];
int Sap(){
int res=0;
BFS();
int top=0;
memcpy(cur,head,sizeof(head));
int u=src,i;
while(dep[src]<n){
if(u==des){
int temp=INF,inser=n;
for(i=0;i!=top;++i){
if(temp>edge[stack[i]].cap){
temp=edge[stack[i]].cap;
inser=i;
}
}
for(i=0;i!=top;++i){
edge[stack[i]].cap-=temp;
edge[stack[i]^1].cap+=temp;
}
res+=temp;
top=inser;
u=edge[stack[top]].from;
}
for(i=cur[u];i!=-1;i=edge[i].next)
if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1)
break;
if(i!=-1){
cur[u]=i;
stack[top++]=i;
u=edge[i].to;
}else{
if(--gap[dep[u]]==0)
break;
int minn=n;
for(i=head[u];i!=-1;i=edge[i].next){
if(edge[i].cap==0)
continue;
if(minn>dep[edge[i].to]){
minn=dep[edge[i].to];
cur[u]=i;
}
}
++gap[dep[u]=minn+1];
if(u!=src)
u=edge[stack[--top]].from;
}
}
return res;
}
int main()
{
int t,x,i,j,ans,tmp,sum;
while(~scanf("%d%d",&n,&m)){
init();
memset(num,0,sizeof(num));
for(i=1;i<=n;i++){
tmp=0;
for(j=1;j<=m;j++){
scanf("%d",&x);
tmp=(tmp<<1)+x;
}
num[tmp]++;
}
sum=n;
src=0;
n=1<<m;
des=n+m+1;
for(i=0;i<n;i++){
if(num[i]){
addedge(src,i+1,num[i]);
tmp=i;
for(j=m;j>=0;j--){
if(tmp&1)
addedge(i+1,n+j,INF);
tmp>>=1;
}
}
}
for(i=1;i<=m;i++){
scanf("%d",&x);
addedge(i+n,des,x);
}
n=des+1;
ans=Sap();
if(ans==sum)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}