bzoj 1834
网络流的模板题
首先第一问我们直接用dinic搞就行了,费用直接存为0(时间上界非常松,这道题是能过),然后第二问我们只需要在第一问
的残余网络上加一个源点,源点指向1号点,容量为k,费用为0,然后对于之前的每一条边,建一个相同的边
容量为无穷大,费用为原来的费用。
//By BLADEVIL var pre, other, len, w :array[0..20100] of longint; last :array[0..2100] of longint; l :longint; n, m, k :longint; father, que, dis :array[0..2100] of longint; flag :array[0..2100] of boolean; a, b, c, d :array[0..20100] of longint; cost :longint; function min(a,b:longint):longint; begin if a>b then min:=b else min:=a; end; procedure connect(a,b,c,d:longint); begin inc(l); pre[l]:=last[a]; last[a]:=l; other[l]:=b; len[l]:=c; w[l]:=d; end; procedure init; var i :longint; begin read(n,m,k); l:=1; for i:=1 to m do read(a[i],b[i],c[i],d[i]); for i:=1 to m do begin connect(a[i],b[i],c[i],0); connect(b[i],a[i],0,0); end; end; function bfs:boolean; var q, p :longint; cur :longint; h, t :longint; begin fillchar(dis,sizeof(dis),0); h:=0; t:=1; que[1]:=1; dis[1]:=1; while t<>h do begin inc(h); cur:=que[h]; q:=last[cur]; while q<>0 do begin p:=other[q]; if (len[q]>0) and (dis[p]=0) then begin inc(t); que[t]:=p; dis[p]:=dis[cur]+1; if p=n then exit(true); end; q:=pre[q]; end; end; exit(false); end; function dinic(x,flow:longint):longint; var q, p :longint; rest, tmp :longint; begin if x=n then exit(flow); rest:=flow; q:=last[x]; while q<>0 do begin p:=other[q]; if (len[q]>0) and (rest>0) and (dis[p]=dis[x]+1) then begin tmp:=dinic(p,min(len[q],rest)); dec(rest,tmp); dec(len[q],tmp); inc(len[q xor 1],tmp); end; q:=pre[q]; end; exit(flow-rest); end; procedure spfa; var q, p :longint; h, t, cur :longint; begin fillchar(flag,sizeof(flag),false); filldword(dis,sizeof(dis) div 4,maxlongint div 10); h:=0; t:=1; que[1]:=n+1; dis[n+1]:=0; while h<>t do begin h:=h mod 2000+1; cur:=que[h]; flag[cur]:=false; q:=last[cur]; while q<>0 do begin if len[q]>0 then begin p:=other[q]; if dis[cur]+w[q]<dis[p] then begin dis[p]:=dis[cur]+w[q]; father[p]:=q; if not flag[p] then begin t:=t mod 2000+1; que[t]:=p; flag[p]:=true; end; end; end; q:=pre[q]; end; end; end; procedure update; var cur :longint; low :longint; begin cur:=n; low:=maxlongint div 10; while cur<>n+1 do begin low:=min(low,len[father[cur]]); cur:=other[father[cur] xor 1]; end; cur:=n; while cur<>n+1 do begin inc(cost,low*w[father[cur]]); dec(len[father[cur]],low); inc(len[father[cur] xor 1],low); cur:=other[father[cur] xor 1]; end; end; procedure main; var ans :longint; i :longint; begin ans:=0; while bfs do ans:=ans+dinic(1,maxlongint div 10); for i:=1 to m do begin connect(a[i],b[i],maxlongint div 10,d[i]); connect(b[i],a[i],0,-d[i]); end; connect(n+1,1,k,0); connect(1,n+1,0,0); while true do begin spfa; if dis[n]=maxlongint div 10 then break; update; end; writeln(ans,' ',cost); end; begin init; main; end.