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
第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。
接下来的各行中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。文件最后一行是2个0,表示结束。
Output
输出的各行中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。若不能确定正确装入信封的任何信件,则输出“none”。
Sample Input
3
1 2
1 3
2 1
0 0
Sample Output
1 1
思路:
如果x与y肯定不在同一个信封里,那么假如一条边不可获缺,那么没有它一定无法完美匹配
于是我们可以枚举每一条边来删除,如果删除后不可以达成完美匹配的话那么这一条边一定是必要的
var
map:array[0..1001,0..1001]of boolean;
cover:array[0..1001]of boolean;
link:array[0..1001]of longint;
i,j,n,s,t,m,x,y,check:longint;
function find(i:longint):boolean;
var
q,k,s:longint;
begin
find:=true;
for k:=1 to n do
if (not(cover[k]))and(map[i,k]) then
begin
q:=link[k];
cover[k]:=true;
link[k]:=i;
if (find(q))or(q=0) then exit;
link[k]:=q;
end;
exit(false);
end;
begin
check:=0;
readln(n);
fillchar(map,sizeof(map),true);
while 1=1 do
begin
read(x,y);
if x+y=0 then break;
map[y,x]:=false;//Y信封中不可以放X
end;
for i:=1 to n do//匈牙利算法
begin
fillchar(cover,sizeof(cover),false);
find(i);
end;
for i:=1 to n do//枚举删边
begin
y:=link[i];
link[i]:=0;
map[y,i]:=false;
fillchar(cover,sizeof(cover),false);
if not(find(y)) then
begin
link[i]:=y;
writeln(i,' ',y);
check:=1;
end;
map[y,i]:=true;
end;
if check=0 then writeln('none');
end.