今天刚学的上下界网络流,概念都还不是很熟。。。
题意立即可以转化成每条边流量下界为1,上界为inf,s向每个点连边,每个点向t连边,下界都为0,上界都为inf,求最小流量。
于是建立超级源和超级汇,按套路先求出一个可行流,记ans1为可行流中t->s这条边的流量。然后删除t->s,再跑一个t到s的最大流(退一些流使总流量变小),记ans2为这次最大流的流量,答案即为ans1-ans2。
要注意ans1不是可行流的总流量,而是s->t的流量,我就这样WA了一发。。。
代码:
type
edge=^edgenode;
edgenode=record
t,c,f:longint;
next,rev:edge;
end;
const maxl=1000000000;
var
n,i,j,x,z,s,t,ss,tt,nows,nowt,ans1,ans2,tot:longint;
ind:array[0..110]of longint;
con:array[0..200]of edge;
ne,dl:array[0..200]of longint;
visit:array[0..200]of boolean;
procedure ins(x,y,z:longint);
var
p:edge;
begin
new(p);
p^.t:=y;
p^.c:=z;
p^.f:=0;
p^.next:=con[x];
con[x]:=p;
new(p);
p^.t:=x;
p^.c:=0;
p^.f:=0;
p^.next:=con[y];
con[y]:=p;
con[x]^.rev:=con[y];
con[y]^.rev:=con[x];
end;
function min(x,y:longint):longint;
begin
if x>y then exit(y)
else exit(x);
end;
function bfs:boolean;
var
p:edge;
head,tail,x:longint;
begin
head:=1;
tail:=1;
dl[1]:=nows;
ne[nows]:=1;
bfs:=false;
while head<=tail do
begin
x:=dl[head];
//writeln(x);
if x=nowt then bfs:=true;
p:=con[x];
while p<>nil do
begin
if (ne[p^.t]=0)and(p^.c>p^.f) then
begin
ne[p^.t]:=ne[x]+1;
inc(tail);
dl[tail]:=p^.t;
end;
p:=p^.next;
end;
inc(head);
end;
end;
function dinic(k,flow:longint):longint;
var
p:edge;
o:longint;
begin
if k=nowt then exit(flow);
if visit[k]=true then exit(0);
p:=con[k];
dinic:=0;
o:=0;
while p<>nil do
begin
if (ne[p^.t]=ne[k]+1)and(p^.c>p^.f) then
begin
o:=dinic(p^.t,min(flow-dinic,p^.c-p^.f));
inc(dinic,o);
inc(p^.f,o);
dec(p^.rev^.f,o);
if dinic=flow then break;
end;
p:=p^.next;
end;
if dinic=0 then visit[k]:=true;
end;
function work():longint;
begin
fillchar(ne,sizeof(ne),0);
work:=0;
while bfs do
begin
fillchar(visit,sizeof(visit),false);
work:=work+dinic(nows,maxl);
fillchar(ne,sizeof(ne),0);
end;
end;
begin
readln(n);
s:=0;t:=n+1;ss:=n+2;tt:=n+3;
fillchar(ind,sizeof(ind),0);
for i:=1 to n do
begin
read(x);
dec(ind[i],x);
for j:=1 to x do
begin
read(z);
inc(ind[z]);
ins(i,z,maxl);
end;
ins(s,i,maxl);
ins(i,t,maxl);
end;
ins(t,s,maxl);
for i:=1 to n do
if ind[i]>0 then ins(ss,i,ind[i])
else ins(i,tt,-ind[i]);
nows:=ss;
nowt:=tt;
work;
ans1:=con[t]^.f;
con[t]:=con[t]^.next;
nows:=t;
nowt:=s;
ans2:=work;
writeln(ans1-ans2);
end.