没什么好说的,去看胡伯涛的论文吧,(不过我没看,我是听莫队长讲解的)。
用的是多路增广的dinic,跑到28名(下面第35名是我的小号先交的,结果一模一样的程序要慢一些>_<)。
还是讲解一下吧。。。
题目不记得了,讲一下构图。核心思想是最大流最小割定理和化点权为边值。将所有正权点与s连(s,i)=c;所有负权点与t连(t,s)=-c
原有依赖关系(i,j)=maxlongint。跑一边最大流,显然割边会在(s,i)和(j,t)上,点集也会被割成两部分A、B,这两部分自然会满足题目中的依赖关系(因为(i,j)=maxlongint任何一条链不会在中间被割开)且s ∈ A, t ∈ B
割掉的(s,i)表示没有选这个正权点 i∈B,(j,t)表示选了这个负权点 j∈A,显然答案=所有正权值-没有选的正权值-abs(选了的负权值)。运用最小割自然可以使减去部分最小,答案最大。
const max=2139062142; maxn=5001; maxm=135001; var n,m,sc,s,t,sum:longint; ans,total:int64; c:boolean; tail:array[0..maxn]of longint; next:array[0..maxm]of longint; sora:array[0..maxm]of integer; flow:array[0..maxm]of int64; pow:array[0..maxm]of longint; d:array[0..maxn]of longint; v:array[0..maxn]of boolean; st:array[1..5500]of integer; function bfs(s:longint):boolean; var h,r,i:longint; begin fillchar(d,sizeof(d),127); fillchar(v,sizeof(v),true); fillchar(st,sizeof(st),0); h:=0;r:=1;st[1]:=s;d[s]:=0;v[s]:=false; repeat inc(h); i:=st[h]; while next[i]<>0 do begin i:=next[i]; if (flow[i]>0)and(v[sora[i]]) then begin d[sora[i]]:=d[st[h]]+1; inc(r);st[r]:=sora[i]; v[sora[i]]:=false end end until h>=r; if d[t]>max then exit(false); exit(true) end; procedure dfsans(x:longint); var i:longint; begin v[x]:=false; inc(total); i:=x; while next[i]<>0 do begin i:=next[i]; if (v[sora[i]])and(flow[i]<>0) then dfsans(sora[i]) end end; function dfs(now,low:longint):longint; var k,tmp:longint; begin if now=t then exit(low); dfs:=0;k:=now; while next[k]<>0 do begin k:=next[k]; if (flow[k]>0)and(d[sora[k]]=d[now]+1) then begin if flow[k]<low then tmp:=dfs(sora[k],flow[k]) else tmp:=dfs(sora[k],low); if tmp=0 then d[sora[k]]:=max; dec(low,tmp); dec(flow[k],tmp); inc(flow[pow[k]],tmp); inc(dfs,tmp); if low=0 then break end end end; procedure dinic; begin ans:=0; while bfs(s) do inc(ans,dfs(s,maxlongint)); ans:=total-ans; total:=0; fillchar(v,sizeof(v),true); dfsans(s); writeln(total-1,' ',ans) end; procedure link(x,y:longint;z:int64); begin inc(sc);sora[sc]:=y;flow[sc]:=z; next[tail[x]]:=sc;tail[x]:=sc; inc(sc);sora[sc]:=x;flow[sc]:=0; next[tail[y]]:=sc;tail[y]:=sc; pow[sc-1]:=sc;pow[sc]:=sc-1 end; procedure init; var i,x,y:longint; begin readln(n,m); fillchar(pow,sizeof(pow),0); fillchar(tail,sizeof(tail),0); fillchar(next,sizeof(next),0); fillchar(sora,sizeof(sora),0); fillchar(flow,sizeof(flow),0); s:=0;t:=n+1;total:=0;sc:=n+1; tail[0]:=0;tail[n+1]:=n+1; for i:=1 to n do begin readln(x);tail[i]:=i; if x>=0 then begin link(s,i,x);total:=total+x end else link(i,t,-x) end; for i:=1 to m do begin readln(x,y); link(x,y,9187201950435737471) end; dinic end; begin while not(seekeof) do init; end.