<题目链接>

题目大意:

  有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国王不满意,他要求大臣给他另一个表,每个王子可以和几个妹子结婚,按序号升序输出妹子的编号,这个表应满足所有的王子最终都有妹子和他结婚。

解题分析:  <转载于 >>> >

  如果王子u喜欢妹子v,则建一条边u指向v(u,v),对于大臣给出的初始完美匹配,如果王子u和妹子v结婚,则建一条边v指向u(v,u),然后求强连通分量。对于每个王子和妹子,如果他们都在同一个强连通分量内,则他们可以结婚。

  为什么呢?因为每个王子只能和喜欢的妹子结婚,初始完美匹配中的丈夫和妻子之间有两条方向不同的边可以互达,则同一个强连通分量中的王子数和妹子数一定是相等的,若王子 x 可以和另外的一个妹子 a 结婚,妹子 a 的原配王子 y 肯定能找到另外一个妹子 b 结婚,因为如果找不到的话,则 x 和 a 必不在同一个强连通分量中。

所以一个王子可以和所有与他同一强连通分量的妹子结婚,而这不会导致同一强连通分量中的其他王子找不到妹子结婚。

(证明:王子为什么不能选择不同强连通分量的妹子:

  反证法:如果强连通分量 1 中的王子选择了强连通分量 2 中的妹子,那么势必强连通分量 2 中的一个王子无法在自己的强连通分量中找到妹子,那么他就会去别的强连通分量找妹子,这样一直循环下去,我们知道最终一定是经过了强连通分量 1,2,x1,x2,xn,……,1,王子们才能都找到自己的妹子,这样这些强连通分量1,2,x1,x2,xn,……,1会构成一个强连通分量,与题设在不同强连通分量中找妹子不符)。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; #define clr(a, b) memset(a, b, sizeof(a))
const int N = 5e3 + ; int n, tot, scc, top;
int stk[N], dfn[N], low[N], belong[N], instack[N], ans[N];
vector<vector<int> > G;
void init() {
tot = scc = top = ;
clr(dfn, );clr(stk, );clr(low, );clr(belong, );clr(instack, );
G.clear(), G.resize(N);
}
void Tarjan(int u) {
low[u] = dfn[u] = ++tot;
stk[++top] = u;
instack[u] = ;
int v;
for (int i = ; i < G[u].size(); i++) {
v = G[u][i];
if (!dfn[v]) {
Tarjan(v);
low[u] = min(low[u], low[v]);
} else if (instack[v]) low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
++scc;
do {
v = stk[top--];
instack[v] = ;
belong[v] = scc; //将该强连通块缩点染色
} while (v != u);
}
}
int main() {
while (scanf("%d", &n) != EOF) {
init();
int k, x;
for (int i = ; i <= n; i++) {
scanf("%d", &k);
while (k--) {
scanf("%d", &x);
G[i].push_back(x + n); //王子编号为1~n,公主编号为n+1~2*n
}
}
for (int i = ; i <= n; i++) {
scanf("%d", &x);
G[x + n].push_back(i); //根据该完美匹配,让公主与对应的王子连边
}
for (int i = ; i <= n; i++) if (!dfn[i]) Tarjan(i);
for (int i = ; i <= n; i++) {
int u = belong[i], v;
clr(ans, ); // ans[]存所有能够与当前王子进行配对的公主
int cur = ;
for (int j = ; j < G[i].size(); j++) { //找出当前王子所在联通块的公主数量
v = belong[G[i][j]];
if (u == v) ans[cur++] = G[i][j];
}
sort(ans, ans + cur);
printf("%d ", cur);
for (int i = ; i < cur; i++) {
printf("%d%s", ans[i] - n, i == cur - ? "\n" : " ");
}
}
}
}

POJ 1904 King's Quest (强连通分量+完美匹配)的更多相关文章

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

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

  2. Poj 1904 King's Quest 强连通分量

    题目链接: http://poj.org/problem?id=1904 题意: 有n个王子和n个公主,王子只能娶自己心仪的公主(一个王子可能会有多个心仪的公主),现已给出一个完美匹配,问每个王子都可 ...

  3. POJ 1904 King's Quest 强连通分量+二分图增广判定

    http://www.cnblogs.com/zxndgv/archive/2011/08/06/2129333.html 这位神说的很好 #include <iostream> #inc ...

  4. POJ - 1904 King's Quest (强连通)

    题意:有N个王子,每个王子有任意个喜欢的妹子,巫师会给出一个方案:每个妹子都嫁给一个王子.但是国王希望知道:每个王子能在哪些妹子中择偶而不影响其他王子择偶. 分析:设王子为x部,妹子为y部,假设有匹配 ...

  5. [poj 1904]King's Quest[Tarjan强连通分量]

    题意:(当时没看懂...) N个王子和N个女孩, 每个王子喜欢若干女孩. 给出每个王子喜欢的女孩编号, 再给出一种王子和女孩的完美匹配. 求每个王子分别可以和那些女孩结婚可以满足最终每个王子都能找到一 ...

  6. poj 1904(强连通分量+完美匹配)

    传送门:Problem 1904 https://www.cnblogs.com/violet-acmer/p/9739990.html 参考资料: [1]:http://www.cnblogs.co ...

  7. poj 1904 King's Quest

    King's Quest 题意:有N个王子和N个妹子;(1 <= N <= 2000)第i个王子喜欢Ki个妹子:(详见sample)题给一个完美匹配,即每一个王子和喜欢的一个妹子结婚:问每 ...

  8. POJ 1904 King's Quest tarjan

    King's Quest 题目连接: http://poj.org/problem?id=1904 Description Once upon a time there lived a king an ...

  9. POJ 1904 King's Quest(SCC的巧妙应用,思维题!!!,经典题)

    King's Quest Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 10305   Accepted: 3798 Ca ...

随机推荐

  1. SQL Server 函数之日期格式化函数

    SQL Server 函数之日期格式化函数 高文龙关注0人评论612人阅读2017-09-23 13:47:07 SQL Server 函数之日期格式化函数 对于一些经常写SQL Server执行语句 ...

  2. 【batch】批处理文件多参数处理和for循环字符串连接

    batch文件写起来,酸爽不谈了.[1]今天在github上发现个好东西batsh,运行地址:https://batsh.org/.[1] 这里需求的场景是:调用run.bat脚本并传入多个参数(相对 ...

  3. Max Sum (dp)

    Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. F ...

  4. laravel 框架后台主菜单接口

    后台菜单调用接口:/admin/manages ManageRepository类: 每个路由中注册: 等等: 最后后台菜单返回:

  5. poj1236 SCC+缩点

    /* 强连通分量内的点可以互相传送,可以直接缩点 缩点后得到一棵树 第一问的答案是零入度点数量, 第二问: 加多少边后变成强连通图 树上入度为0的点有p个,出度为0的点为q,那么答案就是max(p,q ...

  6. AI-DRF权限、频率

    权限 权限逻辑 权限逻辑 权限组件可以设置在三个地方:写在每个类下边表示,访问这个类的数据时,没有权限就不能访问:写在全局,表示访问每个字段的数据都需要权限:还有默认已经也写好了. 写在每个类中:写一 ...

  7. java读取.txt文件工具类FileUtiles

    public class FileUtils { private static final String ENCODING = "UTF-8";//编码方式 /** * 获取文件的 ...

  8. 步步为营-89-SQL语句(删除重复数据)

    1:删除重复数据 --第一步:先找到重复数据 select ProcInstID from record_errorlog group by ProcInstID having count(ProcI ...

  9. 有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'}

    题目:有一个字典对象,d = {'a':1,'b':2},请用尽量简洁的代码将d转换成{1: 'a', 2: 'b'} 第一种方法: d = {'a': 1, 'b': 2}d = {value: k ...

  10. 目标检测算法之Fast R-CNN算法详解

    在介绍Fast R-CNN之前我们先介绍一下SPP Net 一.SPP Net SPP:Spatial Pyramid Pooling(空间金字塔池化) 众所周知,CNN一般都含有卷积部分和全连接部分 ...