题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4685

题解:

这一题是poj 1904的加强版,poj 1904王子和公主的人数是一样多的,并且给出了一个完美匹配,而这一题王子和公主的人数是不同的,而且没有给出任何匹配。因此借鉴1904的做法,我们可以对这题做一些预处理,从而使得它和poj 1904一样能够用强连通分量来求解。

首先求出一个最大匹配,对于每一个没有匹配的王子,加一个虚拟的公主与之匹配,对于每一个没有匹配的公主,加一个虚拟的的王子与之匹配,这样就可以得到一个完美匹配了。并且使得所有的王子都与虚拟的公主连边,所有的公主都与每一个虚拟的王子相连

这样建完图后就可以和poj 1904一样的做法了。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std; const int maxn = ; int scan() {
int ret = , flag = ; char ch;
if ((ch = getchar()) == '-') flag = ;
else if (ch >= ''&&ch <= '') ret = ch - '';
while ((ch = getchar()) >= ''&&ch <= '') ret = ret * + ch - '';
return flag ? -ret : ret;
} void out(int x) {
if (x>) out(x / );
putchar(x % + '');
} int _t[maxn], lef[maxn]; int n, m; vector<int> G[maxn],G2[maxn]; //二分图的最大匹配-----------------------------------------------
bool match(int u) {
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if (!_t[v]) {
_t[v] = ;
if (lef[v]==- || match(lef[v])) {
lef[v] = u;
return true;
}
}
}
return false;
} void BM() {
for (int i = ; i < n; i++) {
memset(_t, , sizeof(_t));
match(i);
}
//for (int i = 0; i < m; i++) {
// printf("lef[%d]:%d\n", i + 1, lef[i]+1);
//}
}
//--------------------------------------------------------------- //tarjan求强连通----------------------------------------------
int pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
stack<int> S; void dfs(int u) {
pre[u] = lowlink[u] = ++dfs_clock;
S.push(u);
for (int i = ; i < G2[u].size(); i++) {
int v = G2[u][i];
if (!pre[v]) {
dfs(v);
lowlink[u] = min(lowlink[u], lowlink[v]);
}
else if (!sccno[v]) {
lowlink[u] = min(lowlink[u], pre[v]);
}
}
if (lowlink[u] == pre[u]) {
scc_cnt++;
for (;;) {
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
if (x == u) break;
}
}
} void find_scc(int n) {
dfs_clock = scc_cnt = ;
memset(sccno, , sizeof(sccno));
memset(pre, , sizeof(pre));
for (int i = ; i < n; i++) {
if (!pre[i]) dfs(i);
}
}
//--------------------------------------------------------------- int vis[maxn];
void solve() {
//build
memset(vis, , sizeof(vis));
int tot_n = n;
//构造完美匹配-----------------------
for (int i = ; i < m; i++) {
if (lef[i] == -) {
lef[i] = tot_n++;
}
vis[lef[i]] = ;
}
int tot_m = m;
for (int i = ; i < tot_n; i++) {
if (vis[i] == ) lef[tot_m++] = i;
}
//------------------- //每一个王子心仪的公主的连边
for (int i = ; i < n; i++) {
for (int j = ; j < G[i].size(); j++) {
int v = G[i][j];
G2[i].push_back(v + tot_n);
}
}
//每一个虚拟的王子与所有的公主的连边
for (int i = n; i < tot_n; i++) {
for (int v = ; v < m; v++) {
G2[i].push_back(v + tot_n);
}
}
//所有的王子与每一个虚拟公主连边
for (int i = m; i < tot_n; i++) {
for (int v = ; v < tot_n; v++) {
G2[v].push_back(i+tot_n);
}
}
//每一个公主与和她匹配的那个王子连边
for (int i = ; i < tot_n; i++) {
G2[i + tot_n].push_back(lef[i]);
} //printf("tot_n:%d\n", tot_n);
//for (int i = 0; i < tot_n * 2; i++) {
// printf("%d:", i + 1);
// for (int j = 0; j < G2[i].size(); j++) {
// int v = G2[i][j]; v++;
// printf("%d ", v);
// }
// printf("\n");
//} //solve
find_scc(tot_n*); //for (int i = 0; i < tot_n * 2; i++) {
// printf("sccno[%d]:%d\n", i + 1, sccno[i]);
//} //print
for (int i = ; i < n; i++) {
vector<int> ans;
for (int j = ; j < G[i].size(); j++) {
int v = G[i][j];
if (sccno[i] == sccno[v + tot_n]) ans.push_back(v);
}
sort(ans.begin(), ans.end());
out(ans.size());
for (int i = ; i < ans.size(); i++) {
putchar(' ');
out(ans[i] + );
}
putchar('\n');
}
} void init() {
for (int i = ; i < maxn; i++) G[i].clear(),G2[i].clear();
memset(lef, -, sizeof(lef));
} int main() {
int tc,kase=;
tc = scan();
while (tc--) {
init();
n = scan(); m = scan();
int ct,v;
for (int i = ; i < n; i++) {
ct = scan();
for (int j = ; j < ct; j++) {
v = scan(); v--;
G[i].push_back(v);
}
}
printf("Case #%d:\n", ++kase);
BM();
solve();
}
return ;
}

hdu 4685 二分匹配+强连通分量的更多相关文章

  1. H - Prince and Princess - HDU 4685(二分匹配+强连通分量)

    题意:有N个王子M个公主,王子喜欢一些公主,而且只能是王子喜欢的人,他们才可以结婚,现在让他们尽可能多的结婚的前提下找出来每个王子都可以和谁结婚. 分析:先求出来他们的最大匹配,因为给的数据未必是完备 ...

  2. Prince and Princess HDU - 4685(匹配 + 强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  3. poj1904 二分图匹配+强连通分量

    http://poj.org/problem?id=1904 Description Once upon a time there lived a king and he had N sons. An ...

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

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

  5. HDU 4685 Prince and Princess (2013多校8 1010题 二分匹配+强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  6. UESTC 898 方老师和缘分 --二分图匹配+强连通分量

    这题原来以为是某种匹配问题,后来好像说是强连通的问题. 做法:建图,每个方老师和它想要的缘分之间连一条有向边,然后,在给出的初始匹配中反向建边,即如果第i个方老师现在找到的是缘分u,则建边u-> ...

  7. hdu 4685 简单匹配+Tarjan算法

    思路:首先看到这题以为能用poj1904的模版直接A掉,WA了几次,然后又TLE了几次.还是想到了正解. 一开始我想的大致方向已经是对的了.先是由王子向每个喜欢的公主建边,再求一次最大匹配,找出匹配后 ...

  8. P5163 WD与地图 [整体二分,强连通分量,线段树合并]

    首先不用说,倒着操作.整体二分来做强连通分量,然后线段树合并,这题就做完了. // powered by c++11 // by Isaunoya #include <bits/stdc++.h ...

  9. HDU 4635 Strongly connected (强连通分量)

    题意 给定一个N个点M条边的简单图,求最多能加几条边,使得这个图仍然不是一个强连通图. 思路 2013多校第四场1004题.和官方题解思路一样,就直接贴了~ 最终添加完边的图,肯定可以分成两个部X和Y ...

随机推荐

  1. POJ C程序设计进阶 编程题#2:四大湖

    编程题#2:四大湖 来源: POJ(Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 我国有4大 ...

  2. IOS基础——静态方法(类方法)和实例方法

    1.实例方法/动态方法 a).标识符:- b).调用方式:(实例对象    函数) c).实例方法在堆栈上. 2.静态方法/类方法 a).标识符:+ b).调用方式:(类    函数) c).静态方法 ...

  3. iOS中UIKit——UIButton设置边框

    UIButton *testButton = [UIButton buttonWithType:UIButtonTypeSystem]; [testButton setFrame:CGRectMake ...

  4. Vue.js学习 Item6 -- Class 与 样式绑定

    数据绑定一个常见需求是操作元素的 class 列表和它的内联样式.因为它们都是 attribute,我们可以用 v-bind 处理它们:只需要计算出表达式最终的字符串.不过,字符串拼接麻烦又易错.因此 ...

  5. Vue.js学习 Item4 -- 数据双向绑定

    Vue.js 的模板是基于 DOM 实现的.这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强.Vue 模板因而从根本上不同于基于字符串的模板,请记住这点. ...

  6. DevExpress之ASPxGridView笔记(1)

    1.设置Row(某列)输出格式,例如,在数字前加美元符.每3位以逗号隔开及设置小数点后两位: <dx:GridViewDataTextColumn FieldName="SHOUHUI ...

  7. 三种找回 linux root密码

    找回 linux root密码的三种方法 第1种方法: 1.在系统进入单用户状态,直接用passwd root去更改2.用安装光盘引导系统,进行linux rescue状态,将原来/分区挂接上来,作法 ...

  8. php常用函数集锦[备份用的]

    1.判断是否正确的日期格式 /** * 是否正确的日期 * * @access public */ private function _isdate($str,$format="Y-m-d ...

  9. java枚举类型使用笔记

    1.values()方法返回枚举所有实例的一个数组,调用这个数组的length方法,可以得到这个枚举对象中实例的个数 2.枚举类的每个实例,其实都是static的,可以通过static方法直接调用,而 ...

  10. 15)Java &和&&

    &,双目运算符:将两个表达式的值按二进制位展开,对应的位(bit)按值进行"与"运算,结果保留在该位上- 比如170&204对应二进制就是      1010101 ...