题目大意:
Small John所提供的n封信依次编号为1,2,…,n;且n个信封也依次编号为1,2,…,n。假定Small John能提供一组信息:第i封信肯定不是装在信封j中。请编程帮助Small John,尽可能多地将信正确地装回信封。
n≤100
题解:
匈牙利算法:
这题我们可以用二分图去实现,先对信封与信之间的关系用匈牙利求一个完美匹配。
然后枚举该匹配中的每一条边,若该边被删除后不能找到增广路,则可以确定这封信一定是装在某个信封中。
代码:
var
map:array [0..501,0..501] of boolean;
cover:array [0..501] of boolean;
link:array [0..501] of longint;
ans,x,y,i,k,n:longint;
check:boolean;
function find(x:longint):boolean;
var
q,i:longint;
begin
for i:=1 to n do
if not(map[x,i]) and not(cover[i]) then
begin
q:=link[i];
link[i]:=x;
cover[i]:=true;
if (q=0) or (find(q)) then exit(true);
link[i]:=q;
end;
exit(false);
end;
begin
readln(n);
readln(x,y);
while (x<>0) or (y<>0) do
begin
map[y,x]:=true;
readln(x,y);
end;
for i:=1 to n do
begin
fillchar(cover,sizeof(cover),false);
find(i);
end;
check:=true;
for i:=1 to n do
begin
fillchar(cover,sizeof(cover),false);
k:=link[i];
map[k,i]:=true;
link[i]:=0;
if not(find(k)) then
begin
writeln(i,' ',k);
link[i]:=k;
check:=false;
end;
map[k,i]:=false;
end;
if check then writeln('none');
end.