传送门:Problem 4685

https://www.cnblogs.com/violet-acmer/p/9739990.html

参考资料:

  [1]:二分图的最大匹配、完美匹配和匈牙利算法

  [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(强连通分量+二分图的完美匹配)的更多相关文章

  1. hdu 4685(强连通分量+二分图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4685 题意:n个王子和m个公主,王子只能和他喜欢的公主结婚,公主可以和所有的王子结婚,输出所有王子可能 ...

  2. POJ 1904 King's Quest ★(强连通分量:可行完美匹配边)

    题意 有n个女生和n个男生,给定一些关系表示男生喜欢女生(即两个人可以结婚),再给定一个初始匹配,表示这个男生和哪个女生结婚,初始匹配必定是合法的.求每个男生可以和哪几个女生可以结婚且能与所有人不发生 ...

  3. (step6.3.5)hdu 1281(棋盘游戏——二分图的完美匹配)

    题目大意:本体是中文题.读者可以直接在OJ上看 解题思路: 1)完美匹配:所有的端点都是匹配点 2)对于二分图的完美匹配,我们需要用一个数组来存储匹配点.(而二分图的其他问题(我们则可以直接使用变量来 ...

  4. codevs 1222 信与信封问题(二分图的完美匹配)

    1222 信与信封问题   题目描述 Description John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出.但是,第二天John的儿子Small John将这n封信都拿出了信封. ...

  5. UVa1349 Optimal Bus Route Design(二分图最佳完美匹配)

    UVA - 1349 Optimal Bus Route Design Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & ...

  6. UVa 11383 少林决胜(二分图最佳完美匹配)

    https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数 ...

  7. Ants(二分图最佳完美匹配)

    Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6904   Accepted: 2164   Special Ju ...

  8. UVA - 1045 The Great Wall Game(二分图最佳完美匹配)

    题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include < ...

  9. HDU 3072 (强连通分量)

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

随机推荐

  1. xcode archive 去掉dsym文件和添加dsym文件

    打包慢,让人发狂!!! 所以我们尝试的去掉一些测试时候用不到的东西 比如DSYM: 这DSYM是收集奔溃的.在测试的时候不需要这些东西的所以去掉就好: 项目  Build Settings -> ...

  2. Pair Work:电梯调度算法的实现和测试 by 12061171 and 12061168

    结队成员简介: 成员:牛强,学号12061171:刘文乔,学号120611683 我们之所以结对编程以完成所给课设要求,是因为我们互相了解彼此,能够更好更快地完成.下图是我们合作编程时的留影: 牛强是 ...

  3. 《Linux内核设计与实现》 第五章学习笔记

    第五章 系统调用 在现代操作系统中,内核提供了进程与内核进行交互的一组接口.有如下作用: 让应用程序受限的访问硬件设备 提供了创新进程并与已有进程进行通信的机制 提供了申请操作系统其它资源的能力 保证 ...

  4. Python学习笔记(三)——条件语句、循环语句

    注:需注意代码的缩进格式 注:需注意代码的缩进格式 注:需注意代码的缩进格式 Python 与其他语言最大的区别就是,Python 的代码块不使用大括号 {} 来控制类,函数以及其他逻辑判断.pyth ...

  5. Eclipse 项目有红感叹号

    问题原因]:工程中classpath中指向的包路径错误 [解决办法]:右键项目名称 BuildPath ---> Configure Build Paht...中,然后上面有几个选项卡找到 Li ...

  6. 软件工程(GZSD2015)学生博客列表

    2015年贵州师范大学软件工程课程学生博客列表 陈小丽 郑倩 唐洁 周娟 李利思 肖俊 罗文豪 周静 徐明艳 毛涛 邓洪虹 岳庆 李盼 安坤 何亚 涂江凤 张义平 杨明颢 杨家堂 胡贵玲 寿克霞 吴明 ...

  7. 【转帖】ARM的两种不同的CPU docker 应该也是支持arm的

    armel和armhf区别选择 知识经验  3年前 (2014-11-07)  20603浏览  1评论 目录 fpu单元 armel与armhf 安装armel和armhf arm-linux-gn ...

  8. 《Effective C#》快速笔记(一)- C# 语言习惯

    目录 一.使用属性而不是可访问的数据成员 二.使用运行时常量(readonly)而不是编译时常量(const) 三.推荐使用 is 或 as 操作符而不是强制类型转换 四.使用 Conditional ...

  9. HTML DOM 節點

    節點: 整個html文檔是文檔節點: 注釋為注釋節點: 文本為文本節點: html元素為元素節點: html包含的內容為html節點. 節點間的關係: 父節點,子節點和同胞節點. html節點為根節點 ...

  10. git如何拉取指定分支的代码

    问题背景: 新项目还在开发阶段,没有正式对外发布,所以开发同事合并代码到develop上(或者其他名称分支上),而不是到master分支上 通过git拉取代码的时候,默认拉取的是master分支,如下 ...