1. 程式人生 > >Codechef : CALLSCHE(網路流)

Codechef : CALLSCHE(網路流)

傳送門

題解: 先強制每個點不休息,然後每個點可以分配一些休息的給其他人。 每個人每天也可以算出必須休息多少天。 用個上下界網路流即可。

(後來發現自己傻逼了,直接最大流看有沒有最大匹配就行了)。

#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(); }