二分图最小覆盖:找到一个点集,使得每条边上至少有一个点在该集合中。
证明二分图最小覆盖=二分图最大匹配:
二分图最大匹配后,每个点都不能找到增广路,而找不到增广路的原因就是至少有一个点已经被匹配了。即这个点在二分图的最大匹配中。而二分图最大匹配中会存在同一条边两个点都在这个点集中的情况,我们只要取一个点即可。
本题当中,将机器A上的模式看作X集合,机器B上的模式看作Y集合,每个任务对应一条边,两点分别为在A,B上的模式,建立二分图。可以看出,最小的重新启动次数就是二分图的最小覆盖——即最大匹配。普通匈牙利算法即可。
Hint:注意一点:读入时要加上这样一句话,否则会WA:
if p*q=0 then continue;
CODE
Program POJ1325;//By_Thispoet
Const
maxn=100;
Var
i,j,m,n,p,q,k,ans :Longint;
pre,other,last :Array[0..maxn*10]of Longint;
res :Array[0..maxn]of Longint;
state :Array[0..maxn]of Boolean;
Function Dfs(i:Longint):Boolean;
var j,k:Longint;
begin
j:=last[i];
while j<>0 do
begin
k:=other[j];
if not state[k] then
begin
state[k]:=true;
if (res[k]=0)or(Dfs(res[k]))then
begin
res[k]:=i;
exit(true);
end;
end;
j:=pre[j];
end;
exit(false);
end;
BEGIN
readln(n,m,k);
while n<>0 do
begin
fillchar(last,sizeof(last),0);
for i:=1 to k do
begin
readln(j,p,q);
if p*q=0 then continue;
pre[i]:=last[p];last[p]:=i;other[i]:=q;
end;
ans:=0;
fillchar(res,sizeof(res),0);
for i:=1 to n do
begin
fillchar(state,sizeof(state),0);
if Dfs(i) then inc(ans);
end;
writeln(ans);
read(n);
if n<>0 then readln(m,k);
end;
END.