Codechef : CALLSCHE(網路流)
阿新 • • 發佈:2018-12-11
題解: 先強制每個點不休息,然後每個點可以分配一些休息的給其他人。 每個人每天也可以算出必須休息多少天。 用個上下界網路流即可。
(後來發現自己傻逼了,直接最大流看有沒有最大匹配就行了)。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e6+50, INF=0x3f3f3f3f;
const int L=73;
int p,d,h,n,hl,hr;
int lim[L],r[L][L],f[L][L][L] ;
int R[L][L],F[L][L],H[L][L],T[L],tot;
int cnt[L][L];
namespace mcmf {
int g[N],cur[N],nt[N],vt[N],c[N],ec;
int M[N],sum,flow,S,T,src,des;
int que[N],lev[N],hd,tl;
inline void init() {
for(int i=1;i<=tot;i++) M[i]=g[i]=0;
ec=1; sum=flow=0;
}
inline void add(int x,int y,int cc) {
if(!cc) return;
nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; c[ec]=cc;
nt[++ec]=g[y]; g[y]=ec; vt[ec]=x; c[ec]=0;
}
inline void add(int x,int y,int low,int up) {M[x]+=low; M[y]-=low; add(x,y,up-low);}
inline bool bfs() {
for(int i=1;i<=tot;i++) lev[i]=0;
lev[S]=1; que[hd=tl=1]=S;
while(hd<=tl) {
int u=que[hd++];
for(int e=g[u];e;e=nt[e]) {
if(!c[e] || lev[vt[e]]) continue;
que[++tl]=vt[e]; lev[vt[e]]=lev[u]+1;
if(vt[e]==T) return true;
}
} return false;
}
inline int dinic(int x,int f) {
if(x==T) return f;
int rs=0;
for(int &e=cur[x];e;e=nt[e]) {
if(!c[e] || (lev[vt[e]]!=lev[x]+1)) continue;
int o=dinic(vt[e],min(f-rs,c[e]));
c[e]-=o; c[e^1]+=o; rs+=o;
if(rs==f) return rs;
} return lev[x]=0, rs;
}
inline int maxflow() {
while(bfs()) {
int t; memcpy(cur+1,g+1,sizeof(int)*T);
while((t=dinic(S,INF))) flow+=t, memcpy(cur+1,g+1,sizeof(int)*T);
} return flow;
}
inline bool check() {
S=++tot; T=++tot; add(des,src,INF);
for(int i=1;i<=tot;i++) {
if(M[i]>0) sum+=M[i], add(i,T,M[i]);
if(M[i]<0) add(S,i,-M[i]);
}
return maxflow()==sum;
}
}
inline void init() {mcmf::init(); tot=0;}
inline void solve() {
p=rd(), d=rd(), h=rd(), n=rd();
for(int i=1;i<=p;i++) lim[i]=rd();
hl=rd(), hr=rd();
for(int i=1;i<=d;i++)
for(int j=1;j<=h;j++)
r[i][j]=rd(), cnt[i][j]=0;
for(int k=1;k<=p;k++)
for(int i=1;i<=d;i++)
for(int j=1;j<=h;j++)
f[k][i][j]=rd(), cnt[i][j]+=f[k][i][j];
for(int i=1;i<=d;i++)
for(int j=1;j<=h;j++)
if(cnt[i][j]<r[i][j]) {puts("No"); return;}
for(int i=1;i<=d;i++) for(int j=1;j<=h;j++) R[i][j]=++tot;
for(int i=1;i<=p;i++) for(int j=1;j<=d;j++) F[i][j]=++tot;
for(int i=1;i<=p;i++) for(int j=1;j<=d;j++) H[i][j]=++tot;
for(int i=1;i<=p;i++) T[i]=++tot;
mcmf::src=++tot; mcmf::des=++tot;
for(int i=1;i<=d;i++)
for(int j=1;j<=h;j++) if(cnt[i][j]>r[i][j]) {
mcmf::add(mcmf::src,R[i][j],cnt[i][j]-r[i][j],cnt[i][j]-r[i][j]);
for(int k=1;k<=p;k++) if(f[k][i][j]) {
if(j<hl || j>hr) mcmf::add(R[i][j],F[k][i],0,1);
else mcmf::add(R[i][j],H[k][i],0,1);
}
}
for(int k=1;k<=p;++k) {
int s=0;
for(int i=1;i<=d;i++) {
int sum=0;
for(int j=1;j<=h;j++) sum+=f[k][i][j];
mcmf::add(H[k][i],F[k][i],1,INF);
mcmf::add(F[k][i],T[k],max(h-n,0),INF);
s+=sum;
}
mcmf::add(T[k],mcmf::des,max(s-lim[k],0),INF);
}
if(mcmf::check()) puts("Yes");
else puts("No");
}
int main() {
for(int T=rd();T;T--) init(), solve();
}