Codevs 1222 信与信封问题

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
题目描述 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;
}

 

posted @ 2017-08-24 14:37  Alex丶Baker  阅读(191)  评论(0编辑  收藏  举报