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