hdu 4685(强连通分量+二分图的完美匹配)
https://www.cnblogs.com/violet-acmer/p/9739990.html
参考资料:
[2]:http://www.cnblogs.com/frog112111/p/3387173.html
题意:
n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能的结婚对象。
必须保证王子与任意这些对象中的一个结婚,都不会影响到剩余的王子的配对数,也就是不能让剩余的王子中突然有一个人没婚可结了。
分析:
这题是poj 1904的加强版,poj 1904的王子和公主数是相等的,这里可以不等,且poj 1904给出了一个初始完美匹配,但是这题就要自己求。
所以只要求出完美匹配之后,就和poj 1904的做法就完全相同了。
那么怎么求出完美匹配呢?一开始我用多重匹配的匈牙利算法来做,但是怎么做都不对.......看了题解才恍然大悟=_=
先说几个坑,这题有点奇怪,就是所有王子都可以争着和同一个公主结婚,只要该王子喜欢该公主,感觉公主有点悲哀呀........
比如:
2 2
1 1
1 1

输出的答案是:
1 1
1 1
而不是
1 1
0
这里就是和poj 1904有点不一样的地方,坑了我好久.........
求完美匹配:
先对原图用匈牙利算法做一遍二分图匹配,但是还有可能剩余一些人还没匹配,只要虚拟出一些节点来匹配剩余的点就行了。
假设王子有剩下的,那么每个剩下的王子就连一个虚拟的公主,这个公主被所有的王子都喜欢。
假设公主有剩下的,那么每个剩下的公主就连一个虚拟的王子,这个王子喜欢所有的公主
这样就构成完美匹配了,接下来就是和poj 1904一样了。
AC代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define pb push_back
#define mem(a,b) memset(a,b,sizeof a)
const int maxn=+++; int n,m;
//===========匈牙利===========
struct Node
{
int matchM[maxn];
int matchW[maxn];
bool check[maxn];
vector<int >edge[maxn];
void Init()
{
mem(matchM,-);
mem(matchW,-);
for(int i=;i < maxn;++i)
edge[i].clear();
}
void addEdge(int u,int v){
edge[u].pb(v);
}
bool Dfs(int u)
{
for(int i=;i < edge[u].size();++i)
{
int to=edge[u][i];
if(!check[to])
{
check[to]=true;
if(matchW[to] == - || Dfs(matchW[to]))
{
matchW[to]=u;
matchM[u]=to;
return true;
}
}
}
return false;
}
void Hungarian()
{
for(int i=;i <= n;++i)
{
mem(check,false);
Dfs(i);
}
}
}_match;
//============================
//============SCC=============
int scc[maxn];
bool vis[maxn];
vector<int >vs;
vector<int >edge[maxn],redge[maxn];
void addEdge(int u,int v)
{
edge[u].pb(v);
redge[v].pb(u);
}
void Dfs(int u)
{
vis[u]=true;
for(int i=;i < edge[u].size();++i)
{
int to=edge[u][i];
if(!vis[to])
Dfs(to);
}
vs.pb(u);
}
void rDfs(int u,int sccId)
{
scc[u]=sccId;
vis[u]=true;
for(int i=;i < redge[u].size();++i)
{
int to=redge[u][i];
if(!vis[to])
rDfs(to,sccId);
}
}
void Scc()
{
mem(vis,false);
vs.clear();
for(int i=;i <= n;++i)
if(!vis[i])
Dfs(i);
mem(vis,false);
int sccId=;
for(int i=vs.size()-;i >= ;--i)
{
int to=vs[i];
if(!vis[to])
rDfs(to,++sccId);
}
}
//============================
void Init()
{
_match.Init();
for(int i=;i < maxn;++i)
edge[i].clear(),redge[i].clear();
}
int main()
{
int T;
scanf("%d",&T);
for(int kase=;kase <= T;++kase)
{
Init();
scanf("%d%d",&n,&m);
for(int i=;i <= n;++i)
{
int k;
scanf("%d",&k);
while(k--)
{
int v;
scanf("%d",&v);
addEdge(i,v+n);
_match.addEdge(i,v+n);
}
}
_match.Hungarian();//匈牙利算法求最大匹配
int all=n+m;
for(int i=;i <= n;++i)
{
if(_match.matchM[i] == -)//为剩余王子匹配虚拟公主
{
all++;
for(int j=;j <= n;++j)//所有王子都喜欢该虚拟公主
addEdge(j,all);
_match.matchM[i]=all;
_match.matchW[all]=i;
}
}
for(int i=n+;i <= n+m;++i)
{
if(_match.matchW[i] == -)//为剩余公主匹配虚拟王子
{
all++;
for(int j=n+;j <= n+m;++j)//该虚拟王子喜欢所有公主
addEdge(all,j);
_match.matchM[all]=i;
_match.matchW[i]=all;
}
}
for(int i=;i <= all;++i)
if(_match.matchM[i] != -)//所有与王子匹配的公主建一条边连向王子
addEdge(_match.matchM[i],i);
Scc();//求强连通分量
printf("Case #%d:\n",kase);
for(int i=;i <= n;++i)
{
int res=;
int ans[maxn];
for(int j=;j < edge[i].size();++j)
{
int to=edge[i][j];
if(scc[i] == scc[to] && to <= m+n)//剔除掉虚拟的公主
ans[res++]=to-n;
}
sort(ans,ans+res);
printf("%d",res);
for(int i=;i < res;++i)
printf(" %d",ans[i]);
printf("\n");
}
}
}
Kosaraju算法
hdu 4685(强连通分量+二分图的完美匹配)的更多相关文章
- hdu 4685(强连通分量+二分图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能 ...
- POJ 1904 King's Quest ★(强连通分量:可行完美匹配边)
题意 有n个女生和n个男生,给定一些关系表示男生喜欢女生(即两个人可以结婚),再给定一个初始匹配,表示这个男生和哪个女生结婚,初始匹配必定是合法的.求每个男生可以和哪几个女生可以结婚且能与所有人不发生 ...
- (step6.3.5)hdu 1281(棋盘游戏——二分图的完美匹配)
题目大意:本体是中文题.读者可以直接在OJ上看 解题思路: 1)完美匹配:所有的端点都是匹配点 2)对于二分图的完美匹配,我们需要用一个数组来存储匹配点.(而二分图的其他问题(我们则可以直接使用变量来 ...
- codevs 1222 信与信封问题(二分图的完美匹配)
1222 信与信封问题 题目描述 Description John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出.但是,第二天John的儿子Small John将这n封信都拿出了信封. ...
- UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)
UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...
- UVa 11383 少林决胜(二分图最佳完美匹配)
https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数 ...
- Ants(二分图最佳完美匹配)
Ants Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6904 Accepted: 2164 Special Ju ...
- UVA - 1045 The Great Wall Game(二分图最佳完美匹配)
题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include < ...
- HDU 3072 (强连通分量)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3072 题目大意:为一个有向连通图加边.使得整个图全连通,有重边出现. 解题思路: 先用Tarjan把 ...
随机推荐
- xcode archive 去掉dsym文件和添加dsym文件
打包慢,让人发狂!!! 所以我们尝试的去掉一些测试时候用不到的东西 比如DSYM: 这DSYM是收集奔溃的.在测试的时候不需要这些东西的所以去掉就好: 项目 Build Settings -> ...
- Pair Work:电梯调度算法的实现和测试 by 12061171 and 12061168
结队成员简介: 成员:牛强,学号12061171:刘文乔,学号120611683 我们之所以结对编程以完成所给课设要求,是因为我们互相了解彼此,能够更好更快地完成.下图是我们合作编程时的留影: 牛强是 ...
- 《Linux内核设计与实现》 第五章学习笔记
第五章 系统调用 在现代操作系统中,内核提供了进程与内核进行交互的一组接口.有如下作用: 让应用程序受限的访问硬件设备 提供了创新进程并与已有进程进行通信的机制 提供了申请操作系统其它资源的能力 保证 ...
- Python学习笔记(三)——条件语句、循环语句
注:需注意代码的缩进格式 注:需注意代码的缩进格式 注:需注意代码的缩进格式 Python 与其他语言最大的区别就是,Python 的代码块不使用大括号 {} 来控制类,函数以及其他逻辑判断.pyth ...
- Eclipse 项目有红感叹号
问题原因]:工程中classpath中指向的包路径错误 [解决办法]:右键项目名称 BuildPath ---> Configure Build Paht...中,然后上面有几个选项卡找到 Li ...
- 软件工程(GZSD2015)学生博客列表
2015年贵州师范大学软件工程课程学生博客列表 陈小丽 郑倩 唐洁 周娟 李利思 肖俊 罗文豪 周静 徐明艳 毛涛 邓洪虹 岳庆 李盼 安坤 何亚 涂江凤 张义平 杨明颢 杨家堂 胡贵玲 寿克霞 吴明 ...
- 【转帖】ARM的两种不同的CPU docker 应该也是支持arm的
armel和armhf区别选择 知识经验 3年前 (2014-11-07) 20603浏览 1评论 目录 fpu单元 armel与armhf 安装armel和armhf arm-linux-gn ...
- 《Effective C#》快速笔记(一)- C# 语言习惯
目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Conditional ...
- HTML DOM 節點
節點: 整個html文檔是文檔節點: 注釋為注釋節點: 文本為文本節點: html元素為元素節點: html包含的內容為html節點. 節點間的關係: 父節點,子節點和同胞節點. html節點為根節點 ...
- git如何拉取指定分支的代码
问题背景: 新项目还在开发阶段,没有正式对外发布,所以开发同事合并代码到develop上(或者其他名称分支上),而不是到master分支上 通过git拉取代码的时候,默认拉取的是master分支,如下 ...