King's Quest

题意:有N个王子和N个妹子;(1 <= N <= 2000)第i个王子喜欢Ki个妹子;(详见sample)题给一个完美匹配,即每一个王子和喜欢的一个妹子结婚;问每一个王子可以有几种选择(在自己喜欢的妹子里面选),并输出可选的妹子的标号(升序);

Sample Input

4 (N)
2 1 2  (Ki)
2 1 2
2 2 3
2 3 4
1 2 3 4 (完美匹配)

Sample Output

2 1 2
2 1 2
1 3
1 4

分析:图匹配问题,1~N为王子的编号,N~2N为妹子的编号;输入有向边;

重点: 对于给定的一组匹配,看做是反向边;即从妹子指回到王子;这样进行Tarjan缩点之后,就可以遍历边(要在王子喜欢的妹子的选...)看是否还在同一个强连通分量中,若妹子还是和王子在同一个scc中,即可婚配;

证明:为什么说还在一个强连通分量中就可以?边一定是连接王子和妹子的,在不重复走一条边的前提下,会知道王子和妹子的个数是相同的;并且每条边都符合王子喜欢妹子的条件;

ps:该题第一次使用了输出外挂,很好用啊!!时间之间减了至少1/10...

思维坑点:认为可以直接在Tarjan缩点时,就把每个强连通分量里面的妹子写入vec[]中;这样之后就可以直接对每个vec排序之后,之后调用belong[]输出所在的scc的个数即妹子的编号。。想法是好的,但是题意啊!!!并不是在一个连通分量的妹子都是这样王子喜欢的。。。所以要遍历边,找到在一个连通分量里面的;

// 532ms
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define pb push_back
template<typename T>
void read(T &m)
{
T x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
m = x*f;
}
template<typename T>
void out(T a)
{
if(a>) out(a/);
putchar(a%+'');
}
const int N = <<;//倍增点数
const int M = ;
int head[M],tot;
struct edge{
int to,w,Next;
}e[M];
void ins(int a,int b,int w = )
{
e[++tot].Next = head[a];
e[tot].to = b;
e[tot].w = w;
head[a] = tot;
}
int pre[N],dfs_clock,low[N];
int belong[N],scc,n;
stack<int> S;
bool stk[N];
void Tarjan(int u)
{
pre[u] = low[u] = ++dfs_clock;
S.push(u);
stk[u] = true;
int v;//点u所在连通分量的出度;
for(int i = head[u];i;i = e[i].Next){
v = e[i].to;
if(pre[v] == ){
Tarjan(v);
low[u] = min(low[u],low[v]);
}else if(stk[v]){
low[u] = min(low[u],pre[v]);
}
}
if(pre[u] == low[u]){//强连通分量的根节点
++scc;
do{
v = S.top();
S.pop();stk[v] = false;
//if(v <= n)
belong[v] = scc;
//else vec[scc].pb(v);
}while(v != u);
}
}
int ans[N];
int main()
{
int v,T,kase = ;
read(n);
rep1(u,,n){
int k;
read(k);
rep0(j,,k){
read(v);
ins(u,v+n);//妹子标号要加上n;
}
}
rep1(u,,n){
read(v);
ins(v+n,u);//反向边***
}
rep1(u,,n)if(pre[u] == )
Tarjan(u);
rep1(u,,n){
int cnt = ;
for(int i = head[u];i;i = e[i].Next){//遍历边
v=e[i].to;
if(belong[u] == belong[v]) //同一个强连通分量
ans[cnt++] = v-n;
}
sort(ans,ans+cnt);
out(cnt);
rep0(i,,cnt){
putchar(' ');
out(ans[i]);
}
puts("");
}
return ;
}

poj 1904 King's Quest的更多相关文章

  1. 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 ...

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

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

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

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

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

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

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

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

  6. poj 1904 King's Quest tarjan求二分图的所有可选最大匹配边

    因为是完美匹配,所以每个点都已经匹配了,那么如果要选择一条别的边,增光路的最后必定找到原来所匹配的点,加上匹配的边,那么就是一个环.所以可选边在一个强连通分量里. #include <iostr ...

  7. POJ 1904 King's Quest 强联通分量+输入输出外挂

    题意:国王有n个儿子,现在这n个儿子要在n个女孩里选择自己喜欢的,有的儿子可能喜欢多个,最后国王的向导给出他一个匹配.匹配有n个数,代表某个儿子和哪个女孩可以结婚.已知这些条件,要你找出每个儿子可以和 ...

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

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

  9. POJ 1904 King's Quest (强连通分量+完美匹配)

    <题目链接> 题目大意: 有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国王不满意,他要求大臣给他另一个表,每个王 ...

随机推荐

  1. 文件I/O(不带缓冲)之creat函数

    本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 也可调用creat函数创建一个新文件. #in ...

  2. PAT 1017

    1017. Queueing at Bank (25) Suppose a bank has K windows open for service. There is a yellow line in ...

  3. 第一章 JavaScript概述

    JavaScript诞生于1995年.它当时的目的是为了验证表单输入的验证.因为在JavaScript 问世之前,表单的验证都是通过服务器端验证.而当时都是电话拨号上网的年代,服务器验证数据是一件非常 ...

  4. tar备份系统

    一.概述 前几天我通过SSH正在调戏汤姆猫(tomcat)的时候,服务器上CentOS突然挂了.开机grub,使用光盘linux rescue修复提示找不到linux分区,然后想mount硬盘备份系统 ...

  5. 解读eXtremeComponents代码结构--转载

    原文地址:http://blog.csdn.net/lark3/article/details/1937466 大致整理了去年写的东西,罗列如下: ec是一系列提供高级显示的开源JSP定制标签,当前的 ...

  6. MySQL(9):数据表的约束(列的属性)

    1.首先我们看一下这个图: 1.NULL| not NULL是否为空      规定一个字段的值是否为NULL 2.Default value 字段默认值属性 常见的是一个字段不能为空,而且存在默认值 ...

  7. linux 中的vim的配置文件的位置

    /etc下面也有一个vimrc:这个文件对所有用户都有效 在用户家目录(/home/用户名:或/root/)下面有一个.viminfo,只针对特定的用户有效

  8. Microsoft Word 的键盘快捷方式

    Microsoft Word 的键盘快捷方式 全部显示 全部隐藏 本帮助文章中描述的键盘快捷方式适用于美式键盘布局.其他键盘布局的键可能与美式键盘上的键 不完全对应. 注释   本文不介绍如何为宏或自 ...

  9. asp.net网页中上传并且浏览pdf文件的实现

    本文主要讲解在asp.net中的gridview中浏览pdf文件.下面来看一下具体的实现: 第一步,使用sqlserver 创建一个数据库表. 第二步,新建一个webform,命名为uploadpdf ...

  10. JavaScript高级程序设计(六):关键字 void 和 delete 使用

    一.void 1.概述:JavaScript中void是一个操作符,该操作符指定要计算一个表达式但是不返回值. 2.语法:JavaScript void (express)   或则 JavaScri ...