恐怖分子
无向图最小费用割,枚举两部分中的节点是{s,t},以S为源,T为汇的最大流的最小值即为答案;
---------------------------------------------------------------------------------------------------------------------
代码:
const
maxn=50;
var
n:longint;
map,map0:array[1..maxn,1..maxn] of longint;
vh,di,dis,pre,his:array[0..maxn] of longint;
function min(a,b:longint):longint; begin if a<b then exit(a) else exit(b); end;
function flow(s,t:longint):longint;
var
i,j,j1,aug,tmp,min:longint;
flag:boolean;
begin
for i:=1 to n do begin vh[i]:=0; dis[i]:=0; di[i]:=1; end; vh[0]:=n;
i:=s; aug:=maxlongint; flow:=0;
while dis[s]<n do begin
his[i]:=aug; flag:=false;
for j:=di[i] to n do
if (map[i,j]>0)and(dis[j]+1=dis[i]) then begin
flag:=true;
if map[i,j]<aug then aug:=map[i,j];
pre[j]:=i; i:=j;
if i=t then begin
inc(flow,aug);
while i<>s do begin
tmp:=i; i:=pre[i];
dec(map[i,tmp],aug); inc(map[tmp,i],aug);
end;
aug:=maxlongint;
end;
break;
end;
if flag then continue;
min:=n-1;
for j:=1 to n do
if (map[i,j]>0)and(dis[j]<min) then begin
j1:=j; min:=dis[j];
end;
di[i]:=j1;
dec(vh[dis[i]]); if vh[dis[i]]=0 then break;
dis[i]:=min+1; inc(vh[dis[i]]);
if i<>s then begin i:=pre[i]; aug:=his[i]; end;
end;
end;
procedure init;
var
i,j:longint;
ch:char;
begin
readln(n);
for i:=1 to n do begin
for j:=1 to n do begin
read(ch); map0[i,j]:=ord(ch)-ord('0');
end;
readln;
end;
end;
function ans:longint;
var
s,t:longint;
begin
ans:=maxlongint;
for s:=1 to n-1 do
for t:=s+1 to n do begin
map:=map0;
ans:=min(ans,flow(s,t));
end;
end;
procedure main;
begin
init;
write(ans);
end;
begin
main;
end.