/*因为n非常大如果正常建边的话会超内存,每种状态的数目共2……10种状状体记录起来,源点与状态建边权值为状态数,状态与星球建边,星球与汇点建边*/
#include<stdio.h> #include<queue> #include<string.h> using namespace std; #define inf 0x3fffffff #define N 3000 struct node { int u,v,w,next; }bian[N*10*4]; int head[N],yong,s,t,dis[N]; void init(){ yong=0; memset(head,-1,sizeof(head)); memset(dis,-1,sizeof(dis)); } void addedge(int u,int v,int w) { bian[yong].u=u; bian[yong].v=v; bian[yong].w=w; bian[yong].next=head[u]; head[u]=yong++; } void bfs() { int u,v,i; queue<int>q; q.push(t); dis[t]=0; while(!q.empty()) { u=q.front(); q.pop(); for(i=head[u];i!=-1;i=bian[i].next) { v=bian[i].v; if(dis[v]==-1) { dis[v]=dis[u]+1; q.push(v); } } } return ; } int ISAP() { int sum=0; bfs(); int gap[N],cur[N],stac[N],top,i; memset(gap,0,sizeof(gap)); for(i=s;i<=t;i++) { gap[dis[i]]++; cur[i]=head[i]; } int k=s; top=0; while(dis[s]<t+1) { if(k==t) { int minn=inf,index; for(i=0;i<top;i++) { int e=stac[i]; if(minn>bian[e].w) { minn=bian[e].w; index=i; } } for(i=0;i<top;i++) { int e=stac[i]; bian[e].w-=minn; bian[e^1].w+=minn; } sum+=minn; top=index; k=bian[stac[top]].u; } for(i=cur[k];i!=-1;i=bian[i].next) { int v=bian[i].v; if(bian[i].w&&dis[k]==dis[v]+1) { cur[k]=i; k=v; stac[top++]=i; break; } } if(i==-1) { int m=t+1; for(i=head[k];i!=-1;i=bian[i].next) if(m>dis[bian[i].v]&&bian[i].w) { m=dis[bian[i].v]; cur[k]=i; } if(--gap[dis[k]]==0)break; gap[dis[k]=m+1]++; if(k!=s) k=bian[stac[--top]].u; } } return sum; } int main() { int bit[N],n,m,i,j,k,tot[N],f; bit[0]=1; for(i=1;i<10;i++) bit[i]=bit[i-1]*2; while(scanf("%d%d",&n,&m)!=EOF) { init(); s=0;t=1024+m+1; memset(tot,0,sizeof(tot)); for(i=1;i<=n;i++) { k=0; for(j=0;j<m;j++) { scanf("%d",&f); k=k+f*bit[j]; } tot[k]++; } for(i=0;i<1024;i++) { if(tot[i]==0)continue; addedge(s,i+1,tot[i]); addedge(i+1,s,0); for(j=0;j<10;j++) if(i&bit[j]) { addedge(i+1,1024+j+1,inf); addedge(1024+j+1,i+1,0); } } for(i=0;i<m;i++) { scanf("%d",&f); addedge(1024+i+1,t,f); addedge(t,1024+i+1,0); } if(ISAP()==n) printf("YES "); else printf("NO "); } return 0; }