Codevs 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
#include<bits/stdc++.h> using namespace std; #define maxn 100000 #define maxm 2333 int n,m,a[maxm][maxm],letter2[maxn],letter1[maxn],ans,ed,q,w; int vis[maxn]; int find(int x) { for(int i=1;i<=n;i++) if(a[x][i]&&!vis[i]) { vis[i]=1; if(!letter1[i]||find(letter1[i])) { letter1[i]=x; return 1; } } return 0; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=1; while(1) { scanf("%d%d",&q,&w); if(!q&&!w) break; a[q][w]=0; } for(int i=1;i<=n;i++) memset(vis,0,sizeof(vis)),ans+=find(i); if(ans!=n) { cout<<"none"; return 0; } bool flag=0; for(int i=1;i<=n;i++) letter2[letter1[i]]=i; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); a[i][letter2[i]]=0; int o=letter1[letter2[i]]; letter1[letter2[i]]=0; if(!find(i)) { printf("%d %d\n",i,letter2[i]); flag=1; } letter1[letter2[i]]=o; a[i][letter2[i]]=1; } if(!flag) { cout<<"none"; return 0; } return 0; }