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把 ...
随机推荐
- shell脚本之特殊符号总结性梳理
# 井号 (comments) 这几乎是个满场都有的符号#!/bin/bash 井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行. # This line ...
- linux-镜像下载
https://blog.csdn.net/sinat_36564972/article/details/81560395 Centos6.5镜像下载 2018年08月10日 11:35:53 深夜搬 ...
- 先埋锅-CF-Valid BFS?-差一点没交上
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> ...
- 作用域&作用域链和with,catch语句&闭包
作用域(函数) 作用域:变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期; 在一些类C编程语言中花括号内的每一段代码都有各自的作用域,而且变量在声明它们的代码段外是不可见的,称之为块 ...
- 20145221 《Java程序设计》实验报告四:Android开发基础
20145221 <Java程序设计>实验报告四:Android开发基础 实验要求 基于Android Studio开发简单的Android应用并部署测试; 了解Android组件.布局管 ...
- python 中的列表(list)
一.生成一个列表 直接生成 L1 = [1, 2, 3, 4, 5] 列表解析式 >>> L2 = [x for x in range(1, 10, 2)] #从1到10的迭代,步长 ...
- dip vs di vs ioc
https://stackoverflow.com/questions/6766056/dip-vs-di-vs-ioc https://docs.microsoft.com/en-us/aspnet ...
- Tomcat7解决java.lang.OutOfMemoryError: PermGen space
上述两参数,可根据实际情况,逐渐调大.
- Maven整理
第一章 Maven安装 1.1 下载Maven库 下载地址:http://maven.apache.org/download.cgi 1.2 解压下载的库,认识Maven库目录 备注: 解压文件尽量不 ...
- FieldGroup绑定的日期类型存储格式的问题
问题 日期存储的时候,当前数据库中存储格式为 "2017-9-5 0:00:00", 而我实现了以后,看到数据库的存储格式为 "Mon Sep 04 00:00:00 C ...