Problem 1202 信与信封问题 from http://acm.fzu.edu.cn/problem.php?pid=1202

来源:互联网 发布:饥荒攻略软件 编辑:程序博客网 时间:2024/05/22 15:15
 Problem 1202 信与信封问题

Accept: 207    Submit: 1069
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 Problem 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

本题有多组输入数据,你必须处理到EOF为止。
每组数据的第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。
接下来的各行中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。输入最后一行是2个0,表示结束。

 Output

对于每组数据,输出的各行中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。若不能确定正确装入信封的任何信件,则输出“none”。
每组输出结束之后,输出一个空行。

 Sample Input

31 21 32 10 0

 Sample Output

1 1

匈牙利匹配。去掉关键边那么匹配数会减少。可知该边是确定的。


#include <iostream>#include <string>#include <algorithm>#include <memory.h>#include <cstdio>#include <cstdlib>#include <vector>using namespace std;int link[101];int v[101];int map[101][101];int n;int back_link[101];struct Node{int a,b;bool operator<(const Node & node)const{return a<node.a;}};Node nodes[101];bool find(int x){for(int i=1;i<=n;++i){if(!map[x][i] && !v[i]){v[i] = 1;if(!link[i] || find(link[i])){link[i] = x;return true;}// not return false}}return false;/*should return false*/}int hungary(){int ans = 0;memset(link, 0, sizeof(link));for(int i=1;i<=n;++i){memset(v, 0, sizeof(v));/*concentrate on this*/if(find(i))ans++;}return ans;}int main(){    //freopen("in.txt", "r", stdin);   int a, b;while(cin>>n){memset(map, 0, sizeof(map));while(scanf("%d%d", &a, &b), a+b){map[a][b] = 1;}int ans = hungary();memcpy(back_link, link, sizeof(link));int cnt = 0;for(int i=1;i<=n;++i){map[back_link[i]][i] = 1;if(hungary()!=ans){Node node;node.a = back_link[i];node.b = i;nodes[cnt++] = node;}map[back_link[i]][i] = 0;}sort(nodes, nodes+cnt);if(cnt==0)cout<<"none"<<endl;else{for(int i=0;i<cnt;++i){printf("%d %d\n", nodes[i].a, nodes[i].b);}}printf("\n");}    //fclose(stdin);}


原创粉丝点击