NKOJ-4189 信与信封的问题<反向建图>
2017-07-04 16:38
246 查看
P4189信与信封问题
时间限制 : - MS 空间限制 : 165536 KB
评测说明 : 1s
问题描述
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,尽可能多地将信正确地装回信封。
输入格式
第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。
接下来的若干行,其中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。
后一行是2个0,表示结束。
输出格式
若干行,其中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。
若不能确定正确装入信封的任何信件,则输出“none”。
样例输入
3
1 2
1 3
2 1
0 0
样例输出
1 1
来源 FJOI 2001
所以我们就反向建图
这样我们就得到了一个 某封信 可能装在 某个信封 的图
其次,一个信封只能装一封信,那么装完信之后我们得到的集合就是一个配对
所以这道题目要用到最大匹配
易得:
假如某一个对应关系是必须的(即可以确定某一封信必须装进某一个信封),那么如果删去这条边,就不能找到一个配对使得每一封信都能够装进一个信封
但假如这个关系不是必须的,那么删掉了,每封信都还是可以在不冲突的情况下全部装进信封里头
也就是说,如果删去某条边之后,最大匹配的边数不为n(信的封数),那么这条边就是必须的,于是就可以输出了
所以我们只需要从小到大枚举每一条边,删掉这条边之后就跑一次最大匹配,如果最大匹配的边数不为n,那么这条边就是必须的
例如
②题目可能在一开始就是无解的,即一开始就无法保证能够把每一封信装进每一个信封,所以要先跑一次
时间限制 : - MS 空间限制 : 165536 KB
评测说明 : 1s
问题描述
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,尽可能多地将信正确地装回信封。
输入格式
第一行是一个整数n(n≤100)。信和信封依次编号为1,2,…,n。
接下来的若干行,其中每行有2个数i和j,表示第i封信肯定不是装在第j个信封中。
后一行是2个0,表示结束。
输出格式
若干行,其中每行有2个数i和j,表示第i封信肯定是装在第j个信封中。请按信的编号i从小到大顺序输出。
若不能确定正确装入信封的任何信件,则输出“none”。
样例输入
3
1 2
1 3
2 1
0 0
样例输出
1 1
来源 FJOI 2001
首先我很好奇为什么John大晚上不睡觉去写信,还写了好几封,这是有多不走心
其次,小John为什么随便翻他爸爸的信,这个国家没点隐私权的么
题解
这道题目的解法很暴力真的很暴力
建图
由于题目给的是否定的答案,但是我们通过一定的否定答案很难推导出肯定答案所以我们就反向建图
哪条边是否定的,我们就删去这条边 而没有被提到的,就建起来
这样我们就得到了一个 某封信 可能装在 某个信封 的图
解题
首先,我们把信放在一遍,把信封放在一边,一个二分图就有了其次,一个信封只能装一封信,那么装完信之后我们得到的集合就是一个配对
所以这道题目要用到最大匹配
易得:
假如某一个对应关系是必须的(即可以确定某一封信必须装进某一个信封),那么如果删去这条边,就不能找到一个配对使得每一封信都能够装进一个信封
但假如这个关系不是必须的,那么删掉了,每封信都还是可以在不冲突的情况下全部装进信封里头
也就是说,如果删去某条边之后,最大匹配的边数不为n(信的封数),那么这条边就是必须的,于是就可以输出了
所以我们只需要从小到大枚举每一条边,删掉这条边之后就跑一次最大匹配,如果最大匹配的边数不为n,那么这条边就是必须的
例如
有信1 2 3,信封4 5 6 1-5 2-5 3-5 1-4 2-4 3-4 1-6 那么如果删去1-6,得到的最大匹配无论如何无法达到3 所以1一定是装在6信封里头 但是其它的边管你怎么删,得到的最大匹配都是3 所以其它任意一条边都是必须的
注意
①删边是在原图上删去一条边,也就是说,删去下一条边的时候,这条边是存在的②题目可能在一开始就是无解的,即一开始就无法保证能够把每一封信装进每一个信封,所以要先跑一次
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n,fath[123]; bool went[123],flag=0; bool maps[123][123]; bool find(int s) { for(int e=1;e<=n;e++) if(maps[s][e]&&!went[e]) { went[e]=1; if(!fath[e]||find(fath[e])) { fath[e]=s; return 1; } } return 0; } int FD() { memset(fath,0,sizeof(fath)); int res=0; for(int i=1;i<=n;i++) { memset(went,0,sizeof(went)); if(find(i))res++; } return res; } int main() { int s,e; memset(maps,1,sizeof(maps)); scanf("%d",&n); while(scanf("%d%d",&s,&e)!=EOF)maps[s][e]=0; if(FD()!=n){printf("none");return 0;} for(int s=1;s<=n;s++) for(int e=1;e<=n;e++) if(maps[s][e]) { maps[s][e]=0; if(FD()!=n){printf("%d %d\n",s,e);maps[s][e]=1;flag=1;break;} maps[s][e]=1; } if(!flag)printf("none"); return 0; }
相关文章推荐
- <logic:iterate>问题
- 工作中遇到的一个有关<textarea></textarea>换行的问题
- 添加 <identity impersonate="true" userName="username" password="password"/>,解决问题!
- asp.net mvc 2 简简单单做开发 使用DataContext扩展方法Find<TEntity>(TEntity obj) 遇到的问题
- 数据库一些基础知识汇总<键类问题小结>
- WCF契约中KnowType之 List<object> & object[]问题
- 简单解决Linq多条件组合问题<转>
- 谈谈Dictionary<T1,T2>和List<T>的问题 [转]
- 数据库死锁问题 及 解决方法 <收藏>
- “无法更新EntitySet“*****”,因为它有一个DefiningQuery,而<ModificationFunctionMapping>元素中没有支持当前操作的<InsertFunction>元素”问题的解决方法
- Iframe 不刷新的问题. 当涉及到与数据库交互时. 用Button不能更新IFrame 好像有缓存在浏览器中, 用<a> 就没问题了
- 数据库死锁问题 及 解决方法 <收藏>
- SQL语句效率问题的几点总结 <转>
- 添加 <identity impersonate="true" userName="username" password="password"/>,解决问题!
- 范型List<>排序的问题解决方案
- >>问题汇总<<
- 在C#里调用C++的dll时需要注意的一些问题<转>
- 谈谈Dictionary<T1,T2>和List<T>的问题