思想:缩点+sap
Max,t还可以缩小,优化,高数课写的,有点丑,暂时懒得改。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<memory.h>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxm=;
const int inf=0x7fffffff;
int vd[maxm],dis[maxm];
int Laxt[maxm],Next[maxm],To[maxm],V[maxm];
int n,m,cnt,ans,s,t;
int a[maxm],c[maxm];
void _update()
{
memset(Laxt,,sizeof(Laxt));
memset(dis,,sizeof(dis));
memset(vd,,sizeof(vd));
memset(a,,sizeof(a));
memset(c,,sizeof(c));
cnt=;
ans=;
}
void _add(int u,int v,int c)
{
Next[cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
V[cnt++]=c;
Next[cnt]=Laxt[v];
Laxt[v]=cnt;
To[cnt]=u;
V[cnt++]=;
}
int _sap(int u,int flow)
{
int tmp,delta=;
if(flow==||u==t) return flow;
for(int i=Laxt[u];i;i=Next[i])
{
if(dis[To[i]]+==dis[u]&&V[i]>){
tmp=_sap(To[i],min(flow-delta,V[i]));
V[i]-=tmp;
V[i^]+=tmp;
delta+=tmp;
if(delta==flow||dis[s]>t) return delta;
}
}
vd[dis[u]]--;
if(vd[dis[u]]==) dis[s]=t+;
vd[++dis[u]]++;
return delta;
}
int main()
{
int n,m,i,j,Max,x;
while(~scanf("%d%d",&n,&m))
{
_update();
Max=;
for(i=;i<=n;i++){
int tmp=;
for(j=;j<=m;j++) {
scanf("%d",&x);
tmp=tmp*+x;
}
if(tmp>Max) Max=tmp;
a[tmp]++;
}
s=;t=Max+m+;
for(i=;i<=m;i++) scanf("%d",&c[i]);
for(i=;i<=Max;i++){
if(a[i]>) {
_add(,i,a[i]);
int k=m,p=i;
while(k&&p){
int tmp=p%;
p/=;
if(tmp>) _add(i,Max+k,inf);
k--;
}
}
}
for(i=;i<=m;i++) _add(Max+i,t,c[i]);
while(dis[s]<=t) {
ans+=_sap(s,inf);
}
if(ans==n) printf("YES\n");
else printf("NO\n");
}
return ;
}