WIKIOI 1222信与信封问题

时间:2021-10-29 21:44:24

题目描述 Description

John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出。但是,第二天John的儿子Small John将这n封信都拿出了信封。不幸的是,Small John无法将拿出的信正确地装回信封中了。

将Small John所提供的n封信依次编号为1,2,…,n;且n个信封也依次编号为1,2,…,n。假定Small John能提供一组信息:第i封信肯定不是装在信封j中。请编程帮助Small John,尽可能多地将信正确地装回信封。

输入描述 Input Description

n文件的第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。

n接下来的各行中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。文件最后一行是2个0,表示结束。

输出描述 Output Description

输出文件的各行中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。若不能确定正确装入信封的任何信件,则输出“none”。

样例输入 Sample Input

3

1  2

1  3

2  1

0  0

样例输出 Sample Output

1   1

数据范围及提示 Data Size & Hint

题解:(摘抄)

典型的二分图最大匹配匈牙利算法

若完美匹配中一条边必须存在, 那如果删掉这条边就不会存在完美匹配

代码:

 var px,py:array[..] of longint;
map:array[..,..] of boolean;
i,n,op,t,x,y,ans:longint;
vis:array[..] of longint;
flag:boolean;
function find(x:longint):boolean;
var i:longint;
begin
for i:= to n do
if map[x,i] then
begin
if (vis[i]=t) then continue;
vis[i]:=t;
if (py[i]=) or (find(py[i])) then
begin
py[i]:=x;
px[x]:=i;
exit(true);
end;
end;
exit(false);
end;
procedure init;
begin
readln(n);
readln(x,y);
fillchar(map,sizeof(map),true);
while (x<>) and (y<>) do
begin
map[x,y]:=false;
readln(x,y);
end;
end;
procedure main;
begin
for i:= to n do
begin
t:=i;
if (find(i)) then inc(ans);
end;
if ans<>n then writeln('none')
else
begin
flag:=false;
fillchar(vis,sizeof(vis),);
for i:= to n do
begin
t:=i;
op:=px[i];
map[i,op]:=false;
py[op]:=;px[i]:=;
if not(find(i)) then
begin
writeln(i,' ',op);
px[i]:=op;
py[op]:=i;
flag:=true;
end;
map[i,op]:=true;
end;
if not(flag) then writeln('none');
end;
end;
begin
init;
main;
end.