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

题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能的结婚对象,

必须保证王子与任意这些对象中的一个结婚,都不会影响到剩余的王子的配对数,也就是不能让剩余的王子中突然有一个人没婚可结了。

分析:这题是poj 1904的加强版,poj 1904的王子和公主数是相等的,这里可以不等,且poj 1904给出了一个初始完美匹配,但是这题就要自己求。

所以只要求出完美匹配之后,就和poj 1904的做法就完全相同了,这里就不在赘述了,可以参考:http://www.cnblogs.com/frog112111/p/3384261.html

那么怎么求出完美匹配呢?一开始我用多重匹配的匈牙利算法来做,但是怎么做都不对.......看了题解才恍然大悟=_=

先说几个坑,这题有点奇怪,就是所有王子都可以争着和同一个公主结婚,只要该王子喜欢该公主,感觉公主有点悲哀呀........

比如:2 2

1 1

1 1

输出的答案是:1 1   而不是  1 1

1 1             0

这里就是和poj 1904有点不一样的地方,坑了我好久.........

求完美匹配:

先对原图用匈牙利算法做一遍二分图匹配,但是还有可能剩余一些人还没匹配,只要虚拟出一些节点来匹配剩余的点就行了

假设王子有剩下的,那么每个剩下的王子就连一个虚拟的公主,这个公主被所有的王子都喜欢。

假设公主有剩下的,那么每个剩下的公主就连一个虚拟的王子,这个王子喜欢所有的公主

这样就构成完美匹配了,接下来就是和poj 1904一样了。

注意:虽然n和m才500,但是数组要开到2000才能过,可能是剩余太多顶点没匹配,所以要虚拟出比较多的顶点吧,我只开到1500,wa到死=_=

还有就是一些细节没处理好也贡献了好多wa,做了一天.........快奔溃了,最后参考别人的代码改来改去才AC,好艰辛,不过最终能过也算安慰了

果然想问题还是不够周全,不够细心

大三了都,哎,弱成一坨翔了~

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int N=;
  6. const int M=+;
  7. struct EDGE{
  8. int v,next;
  9. }edge[M];
  10. int first[N],low[N],dfn[N],sta[M],belong[N];
  11. int ans[N],match[N],flag[N];
  12. bool instack[N],vis[N];
  13. int n,m,g,cnt,top,scc,maxn;
  14. int Scan() //输入外挂
  15. {
  16. int res=,ch,flag=;
  17. if((ch=getchar())=='-')
  18. flag=;
  19. else if(ch>=''&&ch<='')
  20. res=ch-'';
  21. while((ch=getchar())>=''&&ch<='')
  22. res=res*+ch-'';
  23. return flag?-res:res;
  24. }
  25. void Out(int a) //输出外挂
  26. {
  27. if(a>)
  28. Out(a/);
  29. putchar(a%+'');
  30. }
  31. void AddEdge(int u,int v)
  32. {
  33. edge[g].v=v;
  34. edge[g].next=first[u];
  35. first[u]=g++;
  36. }
  37. int min(int a,int b)
  38. {
  39. return a<b?a:b;
  40. }
  41. int max(int a,int b)
  42. {
  43. return a>b?a:b;
  44. }
  45. void init()
  46. {
  47. g=cnt=top=scc=;
  48. memset(first,-,sizeof(first));
  49. memset(dfn,,sizeof(dfn));
  50. memset(instack,false,sizeof(instack));
  51. memset(flag,,sizeof(flag));
  52. //scanf("%d%d",&n,&m);
  53. n=Scan();
  54. m=Scan();
  55. maxn=max(n,m); //王子和公主数可能不同,为了建图方便去较大者,王子编号1--maxn,公主编号maxn+1--2*maxn
  56. }
  57. bool dfs(int u)
  58. {
  59. int i,v;
  60. for(i=first[u];i!=-;i=edge[i].next)
  61. {
  62. v=edge[i].v;
  63. if(!vis[v])
  64. {
  65. vis[v]=true;
  66. if(match[v]==||dfs(match[v]))
  67. {
  68. match[v]=u;
  69. flag[u]=v;
  70. return true;
  71. }
  72. }
  73. }
  74. return false;
  75. }
  76. void xiong() //二分匹配
  77. {
  78. int i;
  79. memset(match,,sizeof(match));
  80. for(i=;i<=maxn;i++)
  81. {
  82. memset(vis,false,sizeof(vis));
  83. dfs(i);
  84. }
  85. }
  86. void Tarjan(int u) //求强连通分量
  87. {
  88. int i,v;
  89. low[u]=dfn[u]=++cnt;
  90. sta[++top]=u;
  91. instack[u]=true;
  92. for(i=first[u];i!=-;i=edge[i].next)
  93. {
  94. v=edge[i].v;
  95. if(!dfn[v])
  96. {
  97. Tarjan(v);
  98. low[u]=min(low[u],low[v]);
  99. }
  100. else if(instack[v])
  101. low[u]=min(low[u],dfn[v]);
  102. }
  103. if(low[u]==dfn[u])
  104. {
  105. scc++;
  106. while()
  107. {
  108. v=sta[top--];
  109. instack[v]=false;
  110. belong[v]=scc;
  111. if(u==v)
  112. break;
  113. }
  114. }
  115. }
  116. void build()
  117. {
  118. int i,k,v,j;
  119. for(i=;i<=n;i++)
  120. {
  121. // scanf("%d",&k);
  122. k=Scan();
  123. while(k--)
  124. {
  125. // scanf("%d",&v);
  126. v=Scan();
  127. AddEdge(i,v+maxn); //王子和喜欢的公主之间连边
  128. }
  129. }
  130.  
  131. xiong(); //做一次二分匹配
  132.  
  133. int all=*maxn;
  134. for(i=;i<=maxn;i++) //为剩余王子匹配虚拟公主
  135. {
  136. if(!flag[i])
  137. {
  138. all++;
  139. for(j=;j<=maxn;j++) //所有王子都喜欢该虚拟公主
  140. AddEdge(j,all);
  141. match[all]=i;
  142. flag[i]=all;
  143. }
  144. }
  145.  
  146. for(i=maxn+;i<=*maxn;i++) //为剩余公主匹配虚拟王子
  147. {
  148. if(!match[i])
  149. {
  150. all++;
  151. for(j=maxn+;j<=*maxn;j++) //该虚拟王子喜欢所有公主
  152. AddEdge(all,j);
  153. flag[all]=i;
  154. match[i]=all;
  155. }
  156. }
  157. for(i=;i<=all;i++) //所有与王子匹配的公主建一条边连向王子
  158. {
  159. if(flag[i])
  160. AddEdge(flag[i],i);
  161. }
  162. }
  163. void solve()
  164. {
  165. int i,u,v;
  166. for(i=;i<=maxn;i++) //求强连通分量
  167. if(!dfn[i])
  168. Tarjan(i);
  169.  
  170. for(u=;u<=n;u++) //枚举所有王子
  171. {
  172. int count=;
  173. for(i=first[u];i!=-;i=edge[i].next)
  174. {
  175. v=edge[i].v;
  176. if(belong[u]==belong[v]) //王子与公主同在一个强连通分量
  177. {
  178. if(v-maxn>m)
  179. continue;
  180. ans[count++]=v-maxn;
  181. }
  182. }
  183. sort(ans,ans+count);
  184. // printf("%d",count);
  185. Out(count);
  186. for(i=;i<count;i++) //输出
  187. {
  188. //printf(" %d",ans[i]);
  189. putchar(' ');
  190. Out(ans[i]);
  191. }
  192. // printf("\n");
  193. putchar('\n');
  194. }
  195. }
  196. int main()
  197. {
  198. int t,cas;;
  199. // scanf("%d",&t);
  200. t=Scan();
  201. for(cas=;cas<=t;cas++)
  202. {
  203. init();
  204. build();
  205. printf("Case #%d:\n",cas);
  206. solve();
  207. }
  208. return ;
  209. }

hdu 4685(强连通分量+二分图)的更多相关文章

  1. hdu 4685(强连通分量+二分图的完美匹配)

    传送门:Problem 4685 https://www.cnblogs.com/violet-acmer/p/9739990.html 参考资料: [1]:二分图的最大匹配.完美匹配和匈牙利算法 [ ...

  2. HDU 3072 (强连通分量)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3072 题目大意:为一个有向连通图加边.使得整个图全连通,有重边出现. 解题思路: 先用Tarjan把 ...

  3. UVa 12167 & HDU 2767 强连通分量 Proving Equivalences

    题意:给出一个有向图,问最少添加几条有向边使得原图强连通. 解法:求出SCC后缩点,统计一下出度为0的点和入度为0的点,二者取最大值就是答案. 还有个特殊情况就是本身就是强连通的话,答案就是0. #i ...

  4. HDU4865 Prince and Princess 强连通分量+二分图判定

    这个题就是建图费点劲,别的和我上一篇博客一样 然后,参考思路请戳这里http://www.cnblogs.com/wally/archive/2013/09/12/3317883.html 补充:这个 ...

  5. POJ 1904 King's Quest 强连通分量+二分图增广判定

    http://www.cnblogs.com/zxndgv/archive/2011/08/06/2129333.html 这位神说的很好 #include <iostream> #inc ...

  6. HDU 4685 Prince and Princess(二分图+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...

  7. hdu 4685 二分匹配+强连通分量

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...

  8. hdu 4685(匹配+强连通分量)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 思路:想了好久,终于想明白了,懒得写了,直接copy大牛的思路了,写的非常好! 做法是先求一次最 ...

  9. 【HDU3861 强连通分量缩点+二分图最小路径覆盖】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 题目大意:一个有向图,让你按规则划分区域,要求划分的区域数最少. 规则如下:1.有边u到v以及有 ...

随机推荐

  1. Bug 14143011 : ORA-19606: CANNOT COPY OR RESTORE TO SNAPSHOT CONTROL FILE

    Bug 14143011 : ORA-19606: CANNOT COPY OR RESTORE TO SNAPSHOT CONTROL FILE [oracle@test]$ tail -f rma ...

  2. Java集合实现类区别与联系

    ArrayList和LinkList相同点和区别: 共性: 都实现了List接口,都是list的实现类,处理list集合操作. 区别: ArrayList:底层存储结构是数组,每个元素都有index标 ...

  3. python opencv show图片,debug技巧

    debug的时候可以直接把图片画出来debug. imshow函数就是python opencv的展示图片的函数,第一个是你要起的图片名,第二个是图片本身.waitKey函数是用来展示图片多久的,默认 ...

  4. Java多线程编程模式实战指南(二):Immutable Object模式

    多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线 ...

  5. 前后端交互json字符串

    //将需要的参数转成json字符串,然后用utf-8编码 var obj = encodeURIComponent(JSON.stringify(this.categories),"utf- ...

  6. 使用jquery-combobox实现select下拉框多选之后,如何将下拉框的值传给input隐藏域

    我在之前的一篇博文中eaeyui-combobox实现组合查询(即实现多个值得搜索)地址:http://www.cnblogs.com/dushan/p/4778897.html 实现了select下 ...

  7. BZOJ3714 PA2014 Kuglarz 最小生成树

    题目传送门 题意:有$N$个盒子,每个盒子中有$0$或$1$个球.现在你可以花费$c_{i,j}$的代价获得$i$到$j$的盒子中球的总数的奇偶性,求最少需要多少代价才能知道哪些盒子中有球.$N \l ...

  8. fastjson tojson部分规则

    fastjson 作为java 目前最快速,最轻便  json对象,与json 字符串转换 第三方包,阿里巴巴提供. 对象转json规则 转json字符串 列 JSONObject.toJSON(ne ...

  9. C# 多线程 Parallel.For 和 For 谁的效率高?那么 Parallel.ForEach 和 ForEach 呢?

    还是那句话:十年河东,十年河西,莫欺少年穷. 今天和大家探讨一个问题:Parallel.For 和 For 谁的效率高呢? 从CPU使用方面而言,Parallel.For 属于多线程范畴,可以开辟多个 ...

  10. Visual Studio 2019 Serial Keys

    Visual Studio 2019 Enterprise BF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 2019 Professional NYWVH-HT ...