匈牙利算法代码及理解
program hungarian;
Type
rec=record
e,next:longint;
end;
Var
a:array[0..200] of rec;
b,last:array[0..100] of longint;//last表示每个节点在匹配中的对应节点是什么,last[i]=0表示i是未盖点
n,m,i,st,ed,ans,top:longint;
v:array[0..100] of boolean;//表示在“每一轮增广”中某个节点有没有访问过
Procedure add(st,ed:longint);
begin
inc(top);
with a[top] do
begin
e:=ed;
next:=b[st];
end;
b[st]:=top;
end;
function dfs(P:longint):boolean;//P下一条总是要找非匹配边
var
u:longint;
y:^rec;
begin
dfs:=false;
u:=b[p];
while u<>b[0] do
begin
y:=@a[u];
u:=y^.next;
if not v[y^.e] then //如果某一个点之前已被访问过表示其已经增广,没有必要再访问
begin
v[y^.e]:=true;
if (last[y^.e]=0) or dfs(last[y^.e]) then
//y^.e是未盖点,直接连一条,继续找非匹配边;y^.e是已盖点,先连非匹配边 P - y^.e 再连匹配边 y^.e - last[y^.e] ,之后只要判断dfs(last[y^.e])即可
begin
last[y^.e]:=p;
last[p]:=y^.e;
exit(true);
end;
end;
end;
exit(false);
end;
begin
readln(n,m);
fillchar(b,sizeof(b),$ff);top:=-1;
for i:=1 to m do
begin
readln(st,ed);
add(st,ed);
add(ed,st);
end;
ans:=0;
for i:=1 to n do
if last[i]=0 then //从未盖点开始增广,但是没有这一行经测试也行= =暂时不知道为什么
begin
fillchar(v,sizeof(v),false); //每一轮清空v数组
inc(ans,ord(dfs(i))); //每增广一次ans++
end;
writeln(ans);
end.
附赠一组数据:
Input
6 22
1 7
1 8
1 9
1 11
2 7
2 8
2 12
3 7
3 8
3 9
3 10
3 12
4 7
4 8
4 9
4 12
5 7
5 10
5 12
6 9
6 11
6 12Output
6
匹配边
1 10
2 8
3 7
4 9
5 12
6 11

浙公网安备 33010602011771号