hdu 4685(匹配+强连通分量)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685
思路:想了好久,终于想明白了,懒得写了,直接copy大牛的思路了,写的非常好!
做法是先求一次最大匹配设为cnt,那么左边有n-cnt个王子还未匹配,右边有m-cnt个公主还未匹配,因此我们将左侧增加m-cnt个虚拟王子,虚拟王子与右边所有公主连边;右边增加n-cnt个虚拟公主,虚拟公主与左边所有王子连边,这样我们就得到一个两边各有M=n+m-cnt的二分图,且该二分图是一个完美匹配。也就是每个王子都有一个匹配的公主。现在,我们将每个王子匹配的公主向该王子喜欢的公主连边(建一个新图g),然后求g的强连通分量。那么与每个王子之前匹配的公主在一个强连通分量里的公主都可以作为该王子的匹配使得最大匹配不变。为什么是这样的呢?设王子i之前的匹配为p[i],现在为王子i选择一个新的公主j,那么我们若能为p[i]重新找到一个王子k,那么实质上就是找到另一个王子互换两个两个王子喜欢的公主。因此两公主若在一个强连通分量里,那么王子由之前的匹配公主A选择公主B时,A也能找到另一个匹配,因为B能够通过某些路径到达A,等价于这条环上所有王子的匹配都后移一个人而已。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
#define MAXN 1111 int n,m,N,cnt;
bool map[MAXN][MAXN];
bool mark[MAXN];
int ly[MAXN];
int lx[MAXN]; int dfs(int u,int m)
{
for(int v=;v<=m;v++){
if(map[u][v]&&!mark[v]){
mark[v]=true;
if(ly[v]==-||dfs(ly[v],m)){
ly[v]=u;
lx[u]=v;
return ;
}
}
}
return ;
} int MaxMatch(int n,int m)
{
memset(ly,-,sizeof(ly));
memset(lx,-,sizeof(lx));
int ans=;
for(int i=;i<=n;i++){
memset(mark,false,sizeof(mark));
ans+=dfs(i,m);
}
return ans;
} vector<vector<int> >g;
vector<vector<int> >ans; int dfn[MAXN],low[MAXN];
int color[MAXN],_count;
stack<int>S; void Tarjan(int u)
{
low[u]=dfn[u]=++cnt;
mark[u]=true;
S.push(u);
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(dfn[v]==){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else if(mark[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
_count++;
int x;
do{
x=S.top();
S.pop();
mark[x]=false;
color[x]=_count;
}while(x!=u);
}
} int main()
{
int _case,k,x,t=;
scanf("%d",&_case);
while(_case--){
scanf("%d%d",&n,&m);
memset(map,false,sizeof(map));
for(int i=;i<=n;i++){
scanf("%d",&k);
while(k--){
scanf("%d",&x);
map[i][x]=true;
}
}
cnt=MaxMatch(n,m);
N=n+m-cnt;
for(int i=n+;i<=N;i++)
for(int j=;j<=N;j++)
map[i][j]=true;
for(int i=m+;i<=N;i++)
for(int j=;j<=N;j++)
map[j][i]=true;
MaxMatch(N,N);
g.clear();
g.resize(N+);
ans.clear();
ans.resize(N+);
for(int i=;i<=N;i++){
for(int j=;j<=N;j++){
if(lx[i]!=j&&map[i][j]){
g[lx[i]].push_back(j);
}
}
}
memset(dfn,,sizeof(dfn));
memset(mark,false,sizeof(mark));
_count=cnt=;
for(int i=;i<=N;i++)
if(dfn[i]==)Tarjan(i);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(map[i][j]&&color[lx[i]]==color[j]){
ans[i].push_back(j);
}
}
}
printf("Case #%d:\n",t++);
for(int i=;i<=n;i++){
printf("%d",(int)ans[i].size());
for(int j=;j<ans[i].size();j++){
printf(" %d",ans[i][j]);
}
puts("");
}
}
return ;
}
hdu 4685(匹配+强连通分量)的更多相关文章
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013480600/article/details/32140501 HDU 3639 Hawk-a ...
- poj1904 二分图匹配+强连通分量
http://poj.org/problem?id=1904 Description Once upon a time there lived a king and he had N sons. An ...
- hdu 4685 二分匹配+强连通分量
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4685 题解: 这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出 ...
- UESTC 898 方老师和缘分 --二分图匹配+强连通分量
这题原来以为是某种匹配问题,后来好像说是强连通的问题. 做法:建图,每个方老师和它想要的缘分之间连一条有向边,然后,在给出的初始匹配中反向建边,即如果第i个方老师现在找到的是缘分u,则建边u-> ...
- H - Prince and Princess - HDU 4685(二分匹配+强连通分量)
题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚. 分析:先求出来他们的最大匹配,因为给的数据未必是完备 ...
- Luogu3731 HAOI2017新型城市化(二分图匹配+强连通分量)
将未建立贸易关系看成连一条边,那么这显然是个二分图.最大城市群即最大独立集,也即n-最大匹配.现在要求的就是删哪些边会使最大匹配减少,也即求哪些边一定在最大匹配中. 首先范围有点大,当然是跑个dini ...
- hdu 4685(强连通分量+二分图的完美匹配)
传送门:Problem 4685 https://www.cnblogs.com/violet-acmer/p/9739990.html 参考资料: [1]:二分图的最大匹配.完美匹配和匈牙利算法 [ ...
- HDU 4685 Prince and Princess(二分图+强连通分量)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:给出n个王子和m个公主.每个王子有一些自己喜欢的公主可以匹配.设最大匹配为M.那么对于每个 ...
- hdu 4685(强连通分量+二分图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能 ...
随机推荐
- Makefile之写demo时的通用Makefile写法
Makefile之写demo时的通用Makefile写法[日期:2013-05-22] 来源:CSDN 作者:gqb666 [字体:大 中 小] 前面的一篇文章Makefile之大型工程项目子目录M ...
- Android 打造完美的侧滑菜单/侧滑View控件
概述 Android 打造完美的侧滑菜单/侧滑View控件,完全自定义实现,支持左右两个方向弹出,代码高度简洁流畅,兼容性高,控件实用方便. 详细 代码下载:http://www.demodashi. ...
- OGNL表达式中的#、%和$
$是el表达式 % #是ognl表达式. http://devilkirin.iteye.com/blog/427375 OGNL表达式非常强大-其中#.%.$这三个符号在OGNL表达式中经常出现 ...
- 摘:"error LNK2019: 无法解析的外部符号 该符号在函数 中被引用" 错误原因
例如“error LNK2019: 无法解析的外部符号error LNK2001: 无法解析的外部符号“private: static struct _OVERLAPPED CUsbCom::g_Wr ...
- centos7下mysqldump+crontab自动备份数据库
1.创建文件夹(存放备份数据) mkdir /bak mkdir /bak/mysqldata 2.编写脚本 vi /usr/sbin/bakmysql.sh 脚本内容如下 DATE=`date +% ...
- Phonegap创建项目语法
1:在本地磁盘新建一个文件夹存放要开发的项目,比如在D盘建一个yun文件夹2 2:然后在dos系统下,d:命令进入d盘,cd yun进入yun文件夹, 3:然后phonegap create yun2 ...
- angular初体验
所有需要ng管理的代码必须被包裹在一个有ng-app指令的元素中ng-app是ng的入口,表示当前元素的所有指令都会被angular管理(对每一个指令进行分析和操作) 利用angular实现双向绑定: ...
- 0069 如何在Intellij IDEA中查看Spring MVC项目的所有请求与处理方法的映射列表
@RequestMapping注解分散于Controller中,如何在一个列表中看到所有的请求呢,比如下面这样: File-->Project Structure-->Modules--& ...
- 好工具 VHD
通过powershell 互转 Convert-VHD –Path F:\debian.vhdx –DestinationPath F:\debian.vhd 举个栗子 附加参考 Convert-VH ...
- 基于HTML5自定义文字背景生成QQ签名档
分享一款利用HTML5实现的自定义文字背景应用,首先我们可以输入需要显示的文字,并且为该文字选择一张背景图片,背景图片就像蒙版一样覆盖在文字上.点击生成QQ签名档即可将文字背景融为一体生成另外一张图片 ...