您的位置:首页 > 其它

codevs 1222 信与信封问题(二分图的完美匹配)

2015-12-25 19:14 483 查看

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

【思路】

二分图的完美匹配。

先一遍match看是否有能够完美匹配,没有则none。如果有枚举删除完美匹配中的边,如果删边后该点不能匹配则输出该边,如果没有则none。

#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#define FOR(a,b,c) for(int a=(b);a<(c);a++)
using namespace std;

const int maxn = 100+10;

bool T[maxn];
int lkx[maxn],lky[maxn];
//lkx 表示与X结点匹配的Y结点 lky表示与Y结点相匹配的X结点
int n,m;
int A[maxn][maxn];

bool match(int u) {
for(int v=1;v<=n;v++)
if(!A[u][v] && !T[v]) {
T[v]=1;
if(!lky[v] || match(lky[v])) {
lky[v]=u , lkx[u]=v;
return true;
}
}
return false;
}

int main() {
scanf("%d",&n);
int u,v;
while(scanf("%d%d",&u,&v)==2 && (u&&v))
A[u][v]=1;
int ans=0;
for(int i=1;i<=n;i++) {
memset(T,0,sizeof(T));
if(match(i)) ans++;
}
if(ans!=n) printf("none\n");
else {
bool flag=0;
for(int i=1;i<=n;i++) {
int v=lkx[i];
A[i][v]=1;
lkx[i]=0 , lky[v]=0;
memset(T,0,sizeof(T));
if(!match(i)) {
printf("%d %d\n",i,v);
lkx[i]=v,lky[v]=i; flag=1;    //恢复
}
A[i][v]=0;                        //恢复
}
if(!flag) puts("none\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: