找到增广路ans+1,至找不到增广
具体参照https://www.byvoid.com/blog/hungary
时间复杂度O(VE)(V表示一侧的点数,E表示二分图的边数)
空间复杂度O(V+E)
UOJ#78. 二分图最大匹配模板测试
var
w:array[0..400000,1..2]of longint;
x,y,z:array[0..600]of longint;
i,j,k:longint;
ans,len,n1,n2,m,a,b:longint;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0
then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
function path(a:longint):longint;
var tt:longint;
begin
tt:=w[a,2];
while tt<>0 do
begin
if y[w[tt,1]]=0
then begin
y[w[tt,1]]:=1;
if (x[w[tt,1]]=0)or(path(x[w[tt,1]])=1)
then begin x[w[tt,1]]:=a; z[a]:=w[tt,1]; exit(1); end;
end;
tt:=w[tt,2];
end;
exit(0);
end;
procedure find;
var i:longint;
begin
for i:=1 to n1 do
begin
fillchar(y,sizeof(y),0);
if path(i)=1 then inc(ans);
end;
end;
begin
readln(n1,n2,m); len:=n1+1;
for i:=1 to m do
begin
readln(a,b);
init(a,b);
end;
ans:=0; fillchar(x,sizeof(x),0);
find;
writeln(ans);
for i:=1 to n1 do
write(z[i],' ');
writeln;
end.
http://blog.csdn.net/acdreamers/article/details/8621130
http://cojs.tk/cogs/problem/problem.php?pid=14
题解:模板题
http://cojs.tk/cogs/problem/problem.php?pid=718
题解:最小路径覆盖模型
http://acm.hdu.edu.cn/showproblem.php?pid=1083
题目大意:判定二分图完备匹配
完备匹配:二分图两侧点集X,Y,假设|X|<|Y|,若有|X|条边将X都匹配上,则存在该二分图的完备匹配
题解:匈牙利求解最大匹配,若等于最小点集则存在完备匹配
const
maxn=405;
var
w,map:array[0..maxn,0..maxn]of longint;
x,y,xl,yl,match:array[0..maxn]of longint;
i,j,k:longint;
n1,n2,n,m,a,b,c,esp:longint;
ans:int64;
function max(a,b:longint):longint;
begin if a>b then exit(a) else exit(b); end;
function min(a,b:longint):longint;
begin if a<b then exit(a) else exit(b); end;
function hungary(a:longint):longint;
var i,tt:longint;
begin
x[a]:=1;
for i:=1 to n do
if (w[a,i]=xl[a]+yl[i])and(y[i]=0) then
begin
y[i]:=1;
if (match[i]=0)or(hungary(match[i])=1)
then begin match[i]:=a; exit(1); end;
end;
exit(0);
end;
procedure km;
var i:longint;
begin
//xl,yl为两边的顶标
//x,y为是否为交替边
fillchar(xl,sizeof(xl),0);
fillchar(yl,sizeof(yl),0);
fillchar(match,sizeof(match),0);
for i:=1 to n do
begin
xl[i]:=-maxlongint;
yl[i]:=0;
for j:=1 to n do
xl[i]:=max(xl[i],w[i,j]);
end;
for i:=1 to n do
while i<=n do
begin
fillchar(x,sizeof(x),0);
fillchar(y,sizeof(y),0);
if hungary(i)=1
then break
else
begin
esp:=maxlongint;
for j:=1 to n do
if x[j]=1
then
for k:=1 to n do
if (y[k]=0)and(esp>xl[j]+yl[k]-w[j,k])
then esp:=xl[j]+yl[k]-w[j,k];
for j:=1 to n do
begin
if x[j]=1 then dec(xl[j],esp);
if y[j]=1 then inc(yl[j],esp);
end;
end;
end;
end;
begin
readln(n1,n2,m); n:=max(n1,n2);
for i:=1 to m do
begin
readln(a,b,c);
w[a,b]:=c;
end;
km;
for i:=1 to n do
ans:=ans+w[match[i],i];
writeln(ans);
end.
http://acm.hdu.edu.cn/diy/contest_show.php?cid=12698
http://acm.hdu.edu.cn/showproblem.php?pid=2255
题解:模板题
http://acm.hdu.edu.cn/showproblem.php?pid=1533
题目大意:给定人和房子的位置,人到房子的花费为他们的曼哈顿距离,询问最小花费
题解:最小权匹配,把权值取相反数,KM求最大匹配,ans=-ans