WIKIOI 1222信与信封问题
题目描述 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
题解:(摘抄)
典型的二分图最大匹配匈牙利算法
若完美匹配中一条边必须存在, 那如果删掉这条边就不会存在完美匹配
代码:
1 var px,py:array[0..100] of longint; 2 map:array[0..100,0..100] of boolean; 3 i,n,op,t,x,y,ans:longint; 4 vis:array[0..100] of longint; 5 flag:boolean; 6 function find(x:longint):boolean; 7 var i:longint; 8 begin 9 for i:=1 to n do 10 if map[x,i] then 11 begin 12 if (vis[i]=t) then continue; 13 vis[i]:=t; 14 if (py[i]=0) or (find(py[i])) then 15 begin 16 py[i]:=x; 17 px[x]:=i; 18 exit(true); 19 end; 20 end; 21 exit(false); 22 end; 23 procedure init; 24 begin 25 readln(n); 26 readln(x,y); 27 fillchar(map,sizeof(map),true); 28 while (x<>0) and (y<>0) do 29 begin 30 map[x,y]:=false; 31 readln(x,y); 32 end; 33 end; 34 procedure main; 35 begin 36 for i:=1 to n do 37 begin 38 t:=i; 39 if (find(i)) then inc(ans); 40 end; 41 if ans<>n then writeln('none') 42 else 43 begin 44 flag:=false; 45 fillchar(vis,sizeof(vis),0); 46 for i:=1 to n do 47 begin 48 t:=i; 49 op:=px[i]; 50 map[i,op]:=false; 51 py[op]:=0;px[i]:=0; 52 if not(find(i)) then 53 begin 54 writeln(i,' ',op); 55 px[i]:=op; 56 py[op]:=i; 57 flag:=true; 58 end; 59 map[i,op]:=true; 60 end; 61 if not(flag) then writeln('none'); 62 end; 63 end; 64 begin 65 init; 66 main; 67 end.