3604WA了,,实在调不动了,,,,
这个题,,直接建图会TLE,,,,
压缩:
把人的可选集合看作一个状态,,,那么,,,最多会有1024个状态,,,而人总数有10万个,,就是说有大量重复,,,于是把这些重复的压缩掉,,,
数据量真的很大,,,memset全部也会TLE,,
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
const int N=2010;
struct edg
{
int to,nxt,w;
}e[N*20];
int h[N],gap[N],p[N],n;
void add(int x,int y,int w,int &j)
{
e[j].to=y;e[j].w=w;e[j].nxt=p[x];p[x]=j++;
e[j].to=x;e[j].w=0;e[j].nxt=p[y];p[y]=j++;
}
int sap(int u,int flow)
{
if(u==n)
return flow;
int tmp=n-1,low=flow;
for(int x=p[u];x!=-1;x=e[x].nxt)
{
int v=e[x].to;
if(h[u]==h[v]+1&&e[x].w)
{
int f=sap(v,min(e[x].w,low));
low-=f;e[x].w-=f;e[x^1].w+=f;
if(low==0||h[n-1]==n)
return flow-low;
}
if(e[x].w)
tmp=min(tmp,h[v]);
}
if(flow==low)
{
if(--gap[h[u]]==0)
h[n-1]=n;
else
gap[h[u]=tmp+1]++;
}
return flow-low;
}
int dp[N];
int sum[22];
int main()
{
int nn,mm;
while(~scanf("%d%d",&nn,&mm))
{
memset(dp,0,sizeof(dp));
for(int i=1;i<=nn;i++)
{
int s=0;
for(int j=0;j<mm;j++)
{
int x;
scanf("%d",&x);
s|=x<<j;
}
dp[s]++;
}
for(int i=0;i<mm;i++)
scanf("%d",&sum[i]);
int tot=1<<mm;
int num=0;
for(int s=0;s<tot;s++)
if(dp[s])
num++;
n=num+mm+2;
int id=1;
int j=0;
fill(p,p+n+1,-1);
for(int s=0;s<tot;s++)
if(dp[s])
{
add(n-1,id,dp[s],j);
for(int k=0;k<mm;k++)
{
int tk=1<<k;
if(tk&s)
add(id,num+k+1,dp[s],j);
}
id++;
}
for(int i=0;i<mm;i++)
add(num+i+1,n,sum[i],j);
fill(h,h+n+1,0);
fill(gap,gap+n+1,0);
gap[0]=n;
int ans=0;
while(h[n-1]<n)
ans+=sap(n-1,1<<29);
puts(ans==nn?"YES":"NO");
}
return 0;
}