类似于那道BZOJ1221软件开发,把每天拆成两个,分别记为Xi,Yi,从S向Yi连一条流量Ai,费用为0的边。从Yi向Yi+1连一条流量maxint。对于每一个医院从Yi向Xi+Dk+1连一条流量为maxint,费用为Qk的边。从Xi向T连一条流量为k,费用为0的边。再对于每个大学都建一个节点Mi,从Mi向X1连一条流量为maxint,费用为Pi的边,从S向Mi连一条流量为Li,费用为0的边。这个网络的最小费用最大流的费用就是答案。开始数组开太大,估计是fillchar花了太多时间就T了。后来把数组改小就A了。
program p3280; const maxn=1000000000; modd=100000; type bian=record next,point,w,f:longint; end; var ii,t,tt,i,j,n,m,k,len,totpoint,totflow,totw,totnum:longint; a,l,pp,q,d:array[1..10000] of longint; b:array[0..200000] of bian; p,after,dis:array[0..10000] of longint; x:array[1..100000] of longint; pd:array[0..10000] of boolean; function min(k1,k2:longint):longint; begin if k1<k2 then exit(k1) else exit(k2); end; procedure ade(k1,k2,k3,k4:longint); begin inc(len); b[len].point:=k2; b[len].next:=p[k1]; b[len].f:=k3; b[len].w:=k4; p[k1]:=len; end; procedure add(k1,k2,k3,k4:longint); begin ade(k1,k2,k3,k4); ade(k2,k1,0,-k4); end; function spfa:boolean; var head,i,j,now:longint; begin fillchar(x,sizeof(x),0); fillchar(pd,sizeof(pd),false); fillchar(dis,sizeof(dis),$3f); fillchar(after,sizeof(after),-1); x[1]:=0; head:=1; now:=0; pd[0]:=true; dis[0]:=0; while head<>now do begin now:=now mod modd+1; i:=p[x[now]]; while i<>-1 do begin j:=b[i].point; if (b[i].f>0) and (b[i].w+dis[x[now]]<dis[j]) then begin dis[j]:=b[i].w+dis[x[now]]; after[j]:=i; if pd[j]=false then begin pd[j]:=true; head:=head mod modd+1; x[head]:=j; end; end; i:=b[i].next; end; pd[x[now]]:=false; end; if after[totpoint]>-1 then exit(true) else exit(false); end; function change:longint; var k,ans,tot,num,i,j:longint; begin i:=totpoint; j:=after[i]; k:=maxn; while j<>-1 do begin k:=min(k,b[j].f); i:=b[j xor 1].point; j:=after[i]; end; ans:=0; i:=totpoint; j:=after[i]; while j<>-1 do begin ans:=ans+k*b[j].w; dec(b[j].f,k); inc(b[j xor 1].f,k); i:=b[j xor 1].point; j:=after[i]; end; totflow:=totflow+k; exit(ans); end; function dinic:longint; var ans:longint; begin ans:=0; while spfa do ans:=ans+change; exit(ans); end; begin readln(t); for tt:=1 to t do begin totnum:=0; readln(n,m,k); len:=-1; fillchar(p,sizeof(p),-1); fillchar(b,sizeof(b),0); for i:=1 to n do begin read(a[i]); totnum:=totnum+a[i]; end; for i:=1 to m do read(l[i],pp[i]); for i:=1 to k do read(d[i],q[i]); for i:=m+1 to m+n-1 do add(i,i+1,maxn,0); for i:=1 to m do begin add(0,i,l[i],0); add(i,m+1,maxn,pp[i]); end; for i:=1 to n do begin add(0,i+n+m,a[i],0); for j:=1 to k do if i+d[j]+1<=n then add(i+n+m,m+i+d[j]+1,maxn,q[j]); end; totpoint:=n+n+m+1; for i:=1 to n do add(m+i,totpoint,a[i],0); totflow:=0; totw:=dinic; if totflow<totnum then writeln('Case ',tt,': impossible') else writeln('Case ',tt,': ',totw); end; end.