POJ 1904 King's Quest (强连通分量+完美匹配)
<题目链接>
题目大意:
有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 (强连通分量+完美匹配)的更多相关文章
- POJ 1904 King's Quest ★(强连通分量:可行完美匹配边)
题意 有n个女生和n个男生,给定一些关系表示男生喜欢女生(即两个人可以结婚),再给定一个初始匹配,表示这个男生和哪个女生结婚,初始匹配必定是合法的.求每个男生可以和哪几个女生可以结婚且能与所有人不发生 ...
- Poj 1904 King's Quest 强连通分量
题目链接: http://poj.org/problem?id=1904 题意: 有n个王子和n个公主,王子只能娶自己心仪的公主(一个王子可能会有多个心仪的公主),现已给出一个完美匹配,问每个王子都可 ...
- POJ 1904 King's Quest 强连通分量+二分图增广判定
http://www.cnblogs.com/zxndgv/archive/2011/08/06/2129333.html 这位神说的很好 #include <iostream> #inc ...
- POJ - 1904 King's Quest (强连通)
题意:有N个王子,每个王子有任意个喜欢的妹子,巫师会给出一个方案:每个妹子都嫁给一个王子.但是国王希望知道:每个王子能在哪些妹子中择偶而不影响其他王子择偶. 分析:设王子为x部,妹子为y部,假设有匹配 ...
- [poj 1904]King's Quest[Tarjan强连通分量]
题意:(当时没看懂...) N个王子和N个女孩, 每个王子喜欢若干女孩. 给出每个王子喜欢的女孩编号, 再给出一种王子和女孩的完美匹配. 求每个王子分别可以和那些女孩结婚可以满足最终每个王子都能找到一 ...
- poj 1904(强连通分量+完美匹配)
传送门:Problem 1904 https://www.cnblogs.com/violet-acmer/p/9739990.html 参考资料: [1]:http://www.cnblogs.co ...
- poj 1904 King's Quest
King's Quest 题意:有N个王子和N个妹子;(1 <= N <= 2000)第i个王子喜欢Ki个妹子:(详见sample)题给一个完美匹配,即每一个王子和喜欢的一个妹子结婚:问每 ...
- 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 ...
- POJ 1904 King's Quest(SCC的巧妙应用,思维题!!!,经典题)
King's Quest Time Limit: 15000MS Memory Limit: 65536K Total Submissions: 10305 Accepted: 3798 Ca ...
随机推荐
- Mac配置Jdk 安装及系统环境配置
注:本文来于< Mac配置Java开发环境 > 1. 下载JDK 从下面链接选择合适版本的安装包进行下载...笔者下载的是jdk-9.0.1 链接:http://www.oracl ...
- Confluence 6 服务器的许可证信息
Confluence 6 服务器的许可证信息. https://www.cwiki.us/display/CONFLUENCEWIKI/Managing+your+Confluence+License
- Confluence 6 中修改默认的表现和内容
Confluence 构建了一些有用的默认设置,这些设置能够让第一次访问使用 Confluence 系统的用户更好的了解系统.同时默认的内容将新空间和其他区域放置在 Confluence 中. Con ...
- 修改Mysql5.7的root密码
Mysql5.7修改root密码 禁用root密码 1.修改 /etc/my.cnf,在 [mysqld] 小节下添加一行:skip-grant-tables=1 这一行配置让 mysqld 启动时不 ...
- python 与mongodb 交互
创建管理员 1 > use admin 2 switched to db admin 3 > db 4 admin 5 > db.createUser({user:'admin',p ...
- LabView(控件部分)
1.虚拟仪器的概述: 虚拟仪器是基于计算机的的仪器,计算机和仪器的密切结合是目前仪器的一个发展方向,大概有两种结合方式,一种是将计算机装入仪器中,实例就是只能化的仪器,流行的嵌入式系统的仪器,另一种就 ...
- poj2836 状态压缩dp
自己的做法是枚举i,j作为顶点的矩形,然后再更新状态S,但是这种做法是错误的 正解是先把所有矩形对求出来,然后枚举状态S,每个处理每个状态时再枚举已经求出的矩形对,用旧状态更新新状态 #include ...
- 数据库MySql的安装
1.MySQL概述 MySQL最初是由“MySQL AB公司”开发的一套关系型数据库管理系统(RDBMS-Relation DataBase Management System).MySQL不仅是最流 ...
- linux添加自定义命令
想添加一个命令, 比如我输入 cdms 按回车, 然后就执行了: cd /mnt/gopath/src/test/app/ 这条命令方法: vi /etc/bashrc 在文件末尾添加 alias c ...
- php模拟数据请求
php:模拟后台接受数据的步骤<?php> 1.连接数据库 $host="localhost"; $uname="root"; $upwd=&quo ...