题目描述 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

 

先找出最大匹配,如果ans != n ,一定输出none,对于每个匹配,删去后如果找不到新的匹配就是合法的

 

#include<bits/stdc++.h>
using namespace std;

bool g[110][110],used[110],flag;
int n,x,y,ans;
int ly[110],lx[110];

bool dfs(int x)
{
    for(int i = 1;i <= n; ++i)
        if(!used[i] && !g[x][i])
        {
             used[i] = 1;
             if(ly[i] == -1 || dfs(ly[i]))
             {
                 ly[i] = x;
                 lx[x] = i;
                 return 1;
             }
        }
    return 0;
}

int main()
{
    scanf("%d",&n);
    while(1)
    {
        scanf("%d%d",&x,&y);
        if(!x && !y) break;
        g[x][y] = 1;
    }
    memset(ly,-1,sizeof(ly));
    ans = 0;
    for(int i = 1;i <= n; ++i)
    {
        memset(used,0,sizeof(used));
        if(dfs(i)) ans++;
    }
    flag = 0;
    if(ans != n) printf("none\n");
    else
    {
        for(int i = 1;i <= n; ++i)
        {
            memset(used,0,sizeof(used));
            g[i][lx[i]] = 1; ly[lx[i]] = -1;
            int t = lx[i];
            lx[i] = 0;
            if(!dfs(i))
            {
                printf("%d %d\n",i,t);
                ly[t] = i;
                lx[i] = t;
                flag = 1;
            }
            g[i][t] = 0;
        }
        if(!flag) printf("none\n");
    }
    return 0;
}