Prince and Princess

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 2281    Accepted Submission(s): 677

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685

Description:

There are n princes and m princesses. Princess can marry any prince. But prince can only marry the princess they DO love.
For all princes,give all the princesses that they love. So, there is a maximum number of pairs of prince and princess that can marry.
Now for each prince, your task is to output all the princesses he can marry. Of course if a prince wants to marry one of those princesses,the maximum number of marriage pairs of the rest princes and princesses cannot change.

Input:

The first line of the input contains an integer T(T<=25) which means the number of test cases.
For each test case, the first line contains two integers n and m (1<=n,m<=500), means the number of prince and princess.
Then n lines for each prince contain the list of the princess he loves. Each line starts with a integer ki(0<=ki<=m), and then ki different integers, ranging from 1 to m denoting the princesses.

Output:

For each test case, first output "Case #x:" in a line, where x indicates the case number between 1 and T.
Then output n lines. For each prince, first print li, the number of different princess he can marry so that the rest princes and princesses can still get the maximum marriage number.
After that print li different integers denoting those princesses,in ascending order.

Sample Input:

  1. 2
  2. 4 4
  3. 2 1 2
  4. 2 1 2
  5. 2 2 3
  6. 2 3 4
  7. 1 2
  8. 2 1 2

Sample Output:

  1. Case #1:
  2. 2 1 2
  3. 2 1 2
  4. 1 3
  5. 1 4
  6. Case #2:
  7. 2 1 2

题意:

给出n个王子,m个公主,然后每个王子都有自己喜欢的公主,公主可以接受所有的王子。。现在要求输出每个王子可以的结婚对象,并且他们结婚过后不影响到最大匹配数量。

题解:

先可以参考下POJ1904的题解

然后这个题和POJ1904的不同就在于,这个题n和m是不等的,一开始的最大匹配也没有给出。

在理解了POJ1904的做法过后,对于这道题就考虑一开始利用二分图匹配自己构造一个最大匹配出来。然后将模型转化为上个题的模型:构造虚拟结点使得n,m相等。

具体的构造方法就是有多少单身王子,就构造多少个虚拟公主;有多少个虚拟公主,就构造多少个虚拟王子,并且将虚拟生物与所有异性进行连边。这样就可以使得所有人中没有单身。那么这个问题就转化为上一个问题了,之后就利用POJ1904的方法来做,注意一下输出即可。

我这里二分图匹配写拐了。。太菜了啊,debug了好久。

代码如下:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <iostream>
  5. #include <queue>
  6. #include <stack>
  7. #include <vector>
  8. using namespace std;
  9. typedef long long ll;
  10. const int N = ;
  11. int t;
  12. int n,m,tot;
  13. int match[N],head[N],link[N][N],check[N];
  14. stack <int> s;
  15. vector <int> ans;
  16. int T,num;
  17. int scc[N],dfn[N],low[N],vis[N];
  18. struct Edge{
  19. int u,v,next;
  20. }e[N*N];
  21. void adde(int u,int v){
  22. e[tot].v=v;e[tot].u=u;e[tot].next=head[u];head[u]=tot++;
  23. }
  24. void Tarjan(int u){
  25. dfn[u]=low[u]=++T;vis[u]=;
  26. s.push(u);
  27. for(int i=head[u];i!=-;i=e[i].next){
  28. int v=e[i].v;
  29. if(!vis[v]){
  30. Tarjan(v);
  31. low[u]=min(low[u],low[v]);
  32. }else if(!scc[v]){
  33. low[u]=min(low[u],dfn[v]);
  34. }
  35. }
  36. if(low[u]==dfn[u]){
  37. num++;int now;
  38. do{
  39. now = s.top();s.pop();
  40. scc[now]=num;
  41. }while(!s.empty() && now!=u);
  42. }
  43. }
  44. int dfs(int x,int nown){
  45. for(int i=;i<=nown;i++){
  46. if(!check[i] && link[x][i]){
  47. check[i]=;
  48. if(match[i]==- || dfs(match[i],nown)){
  49. match[i]=x;
  50. return ;
  51. }
  52. }
  53. }
  54. return ;
  55. }
  56. int hungry(int n1,int m1){
  57. memset(match,-,sizeof(match));
  58. int ans=;
  59. for(int i=;i<=n1;i++){
  60. memset(check,,sizeof(check));
  61. ans+=dfs(i,m1);
  62. }
  63. return ans ;
  64. }
  65. void init(){
  66. memset(link,,sizeof(link));
  67. memset(match,-,sizeof(match));
  68. memset(head,-,sizeof(head));
  69. memset(scc,,sizeof(scc));
  70. memset(dfn,,sizeof(dfn));
  71. memset(vis,,sizeof(vis));
  72. num=;T=;tot=;
  73. }
  74. int main(){
  75. cin>>t;
  76. int Case = ;
  77. while(t--){
  78. Case++;
  79. init();
  80. scanf("%d%d",&n,&m);
  81. for(int i=,k;i<=n;i++){
  82. scanf("%d",&k);
  83. for(int j=,l;j<=k;j++){
  84. scanf("%d",&l);
  85. link[i][l]=;
  86. }
  87. }
  88. int cnt=hungry(n,m);
  89. int nown,nowm;
  90. nown=nowm=n+m-cnt;
  91. for(int i=n+;i<=nown;i++){
  92. for(int j=;j<=nown;j++){
  93. link[i][j]=;
  94. }
  95. }
  96. for(int i=;i<=n;i++){
  97. for(int j=m+;j<=nowm;j++){
  98. link[i][j]=;
  99. }
  100. }
  101. hungry(nown,nowm);
  102. for(int i=;i<=nown;i++){
  103. for(int j=;j<=nowm;j++){
  104. if(link[i][j]) adde(i,nown+j);
  105. }
  106. }
  107. for(int i=;i<=nown;i++){
  108. if(match[i]!=-) adde(i+nown,match[i]);
  109. }
  110. printf("Case #%d:\n",Case);
  111. while(!s.empty()) s.pop();
  112. for(int i=;i<=*nown;i++){
  113. if(!vis[i]) Tarjan(i);
  114. }
  115. for(int i=;i<=n;i++){
  116. ans.clear();
  117. for(int j=head[i];j!=-;j=e[j].next){
  118. int v=e[j].v;v-=nown;
  119. if(v>m) continue ;
  120. if(scc[i]==scc[v+nown]) ans.push_back(v);
  121. }
  122. sort(ans.begin(),ans.end());
  123. printf("%d",(int)ans.size());
  124. for(int j=;j<ans.size();j++){
  125. printf(" %d",ans[j]);
  126. }
  127. printf("\n");
  128. }
  129. }
  130. return ;
  131. }

HDU4685:Prince and Princess(二分图匹配+tarjan)的更多相关文章

  1. HDU 4685 Prince and Princess 二分图匹配+tarjan

    Prince and Princess 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 Description There are n pri ...

  2. 强连通+二分匹配(hdu4685 Prince and Princess)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  3. HDU4685 Prince and Princess 完美搭配+良好的沟通

    意甲冠军:今天,有n王子,m公主.现在给他们配对,与王子会嫁给一个男人,他喜欢.公主无法做出选择. 这标题去咬硬,还有一类似的题目poj1904.那个题目也是给王子与公主配对,但那个是王子公主各n个, ...

  4. HDU4685 Prince and Princess【强连通】

    题意: 有n个王子和m个公主,每个王子都会喜欢若干个公主,也就是王子只跟自己喜欢的公主结婚,公主就比较悲惨, 跟谁结婚都行.然后输出王子可能的结婚对象,必须保证王子与任意这些对象中的一个结婚,都不会影 ...

  5. HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  6. Prince and Princess HDU - 4685(匹配 + 强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  7. UVA - 10635 Prince and Princess LCS转LIS

    题目链接: http://bak.vjudge.net/problem/UVA-10635 Prince and Princess Time Limit: 3000MS 题意 给你两个数组,求他们的最 ...

  8. poj1904 二分图匹配+强连通分量

    http://poj.org/problem?id=1904 Description Once upon a time there lived a king and he had N sons. An ...

  9. P3731 二分图匹配必经边

    题意经过一番转换变成了 让你在一个二分图上删一条边使得二分图的最大独立集大小至少+1 二分图的最大独立集=点数-最小点覆盖(最大匹配) 点数是固定不变的 所以我们要减少最大匹配数 则删掉的哪一条边必须 ...

随机推荐

  1. 统计hive库表在具体下所有分区大小

    1 查询具体表分区大小,以字节展示 hadoop fs -du /user/hive/warehouse/treasury.db/dm_user_excercise > dm_user_exce ...

  2. [python]np.loadtxt报错

    np.loadtxt报错 通过pandas生成的cvs数据利用nump.loadtxt读取的时候 tmp = np.loadtxt('test.csv', dtype=np.str, delimite ...

  3. [Clr via C#读书笔记]Cp3共享程序集和强命名程

    Cp3共享程序集和强命名程序集 私有方式部署+全局方式部署:弱命名程序集+强命名程序集 强命名程序集使用发布者的公钥私钥进行签名,唯一标识发布者. 共享dll被全部复制到System32中 强命名程序 ...

  4. C++ 学习笔记之——字符串和字符串流

    1. 字符数组 字符数组,也就是存放字符类型数据的数组,只不过字符数组的结尾必须是 '\0'.C++ 已经提供了一些字符串处理函数,这些函数被封装在头文件 和 <string.h> 中. ...

  5. 《剑指Offer》题五十一~题六十

    五十一.数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数.例如,在数组{7, 5, 6, 4}中,一共存 ...

  6. 2017-2018-2 20172314 『Java程序设计』课程 结对编程练习_四则运算

    相关过程截图 截图为我负责的部分关于计算的测试 关键代码解释 根据代码中的部分解释,这部分代码实现了结果的整数和分数的输出,如果算出的结果为一个真分数,就输出真分数的形式,如果结果为整数,就输出整数形 ...

  7. No Route to Host from master/192.168.2.131 to master:9000 failed on socket t

    host里边添加的ip地址与当前的ip地址(ifconfig可以查看)不一致,修改当前ip地址就可以了.

  8. 我爱C语言

    各位同志们好,我是来自计算机系的谢畅,我是一个平时看起来高冷其实很逗比的人,我的爱好有很多但只是会一些基础比如游泳,篮球,听听音乐什么的.我的特长是弹吉他虽然弹得不是很溜,我还喜欢朗诵.刚开始我并不是 ...

  9. phpcms免登录cookies设置方案

    PHPCMS的SESSION时间长一些的解决办法修改两个文件: phpsso_server/caches/configs/system.php里的 'session_ttl' => 999999 ...

  10. Spline样条函数 //C++关键字:operator // 重载函数 // 隐含的this指针 // 指针和const限定符

    在数学学科数值分析中,样条是一种特殊的函数,由多项式分段定义.样条插值是使用一种名为样条的特殊分段多项式进行插值的形式.由于样条插值可以使用低阶多项式样条实现较小的差值误差,这样就避免了使用高阶多项式 ...