博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj 1904 强连通分量 tarjan
阅读量:5024 次
发布时间:2019-06-12

本文共 4299 字,大约阅读时间需要 14 分钟。

King's Quest
Time Limit: 15000MS   Memory Limit: 65536K
Total Submissions: 6569   Accepted: 2342
Case Time Limit: 2000MS

Description

Once upon a time there lived a king and he had N sons. And there were N beautiful girls in the kingdom and the king knew about each of his sons which of those girls he did like. The sons of the king were young and light-headed, so it was possible for one son to like several girls.
So the king asked his wizard to find for each of his sons the girl he liked, so that he could marry her. And the king's wizard did it -- for each son the girl that he could marry was chosen, so that he liked this girl and, of course, each beautiful girl had to marry only one of the king's sons.
However, the king looked at the list and said: "I like the list you have made, but I am not completely satisfied. For each son I would like to know all the girls that he can marry. Of course, after he marries any of those girls, for each other son you must still be able to choose the girl he likes to marry."
The problem the king wanted the wizard to solve had become too hard for him. You must save wizard's head by solving this problem.

Input

The first line of the input contains N -- the number of king's sons (1 <= N <= 2000). Next N lines for each of king's sons contain the list of the girls he likes: first Ki -- the number of those girls, and then Ki different integer numbers, ranging from 1 to N denoting the girls. The sum of all Ki does not exceed 200000.
The last line of the case contains the original list the wizard had made -- N different integer numbers: for each son the number of the girl he would marry in compliance with this list. It is guaranteed that the list is correct, that is, each son likes the girl he must marry according to this list.

Output

Output N lines.For each king's son first print Li -- the number of different girls he likes and can marry so that after his marriage it is possible to marry each of the other king's sons. After that print Li different integer numbers denoting those girls, in ascending order.

Sample Input

42 1 22 1 22 2 32 3 41 2 3 4

Sample Output

2 1 22 1 21 31 4

Hint

This problem has huge input and output data,use scanf() and printf() instead of cin and cout to read data to avoid time limit exceed.

Source

 
推导来自这里:http://www.cnblogs.com/ZShogg/archive/2013/03/24/2978513.html

分析:这个题的建图方法很特别。为了充分利用条件,即最后给出的那个完美匹配,将每个王子向他的梦中情人作一条有向边,完美匹配方案中,美女向匹配的王子作一条有向边。求出图中的强连通分量,与王子在同一个强连通分量且该王子喜欢的美女就是答案。

正确性:王子集合{x1,x2,......,xn},美女集合{y1,y2,......,yn},假设在原完美匹配方案中每个匹配都是 (xi,yi),显然yi是xi的一个选项。假如xi选了yj(j!=i),则原先与yj匹配的王子xj要找另一个女人,yi要与另一个王子匹配,假如 xj喜欢yi,那么yj就可以是xi的另一个选项了,假如xj不喜欢yi,那么就继续下去拆散现有的完美匹配,直到有个王子喜欢yi。所以这样就相当于要 找一条由xi出发到yi的通路(等价于由xi出发回到xi的回路),只要这样的回路存在,王子就可以与回路中任意一个他喜欢的美女匹配了。这样也就相当于 求包含xi的强连通分量。(注意:求出强连通分量之后,只有王子喜欢的美女才能匹配)。

 

算法和他想的差不多,其中tarjan犯错的地方为:1.当找到一个强连通分量时,不能记录其上所有boy的喜好;2.再敲tarjan之前还纠结过一个点属于多个强连通分量的情况。。。其实这多个就是一个,AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define LL long long#define ULL unsigned long long#define UINT unsigned int#define MAX_INT 0x7fffffff#define MAX_LL 0x7fffffffffffffff#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))#define MAXN 4444#define MAXM 444444struct edge{ int u,v,nxt;}e[MAXM];int cc,h[MAXN],ins[MAXN];int dfn[MAXN],low[MAXN],vis[MAXN];int m[2010][2010];int tsp,sta[MAXN],top,sn;int N,M;vector
g[MAXN];int c[MAXN];inline void add(int u, int v){ e[cc]=(edge){u, v, h[u]}; h[u]=cc++;}void tarjan(int s){ low[s]=dfn[s]=++tsp; vis[s]=ins[s]=1; sta[top++]=s; for(int i=h[s]; i!=-1; i=e[i].nxt){ int v=e[i].v; if(!vis[v]) tarjan(v),low[s]=MIN(low[s], low[v]); else if(ins[v]) low[s]=MIN(low[s], dfn[v]); } if(low[s]==dfn[s]){ //strongly connnected circle int v; do{ v=sta[--top]; if(v>N){ //girl g[sn].push_back(v); } else c[v]=sn; //boy, hash ins[v]=0; }while(v!=s); sort(g[sn].begin(), g[sn].end()); sn++; }}int ans[MAXN];void solve(int n){ memset(ins, 0, sizeof(ins)); memset(vis, 0, sizeof(vis)); tsp=top=0; sn=0; for(int i=1; i<=n; i++) if(!vis[i]) tarjan(i); for(int i=1; i<=n; i++){ vector
ans; int j=c[i]; //cout<
<

 

转载于:https://www.cnblogs.com/ramanujan/p/3286162.html

你可能感兴趣的文章
iOS计算富文本(NSMutableAttributedString)高度
查看>>
2017/09/15 ( 框架2)
查看>>
三、模版的使用
查看>>
hihoCoder 1174 拓扑排序·一
查看>>
git 的更新代码的取消
查看>>
UVA - 1103 Ancient Messages
查看>>
《数据挖掘与数据化运营实战 思路、方法、技巧与应用》—— 读书笔记
查看>>
office note 解决标签页消失的问题
查看>>
现代密码学:RSA算法
查看>>
Core Image 制作自己的美图秀秀
查看>>
每天一个随笔
查看>>
-------------------python博客目录:-------------------
查看>>
【CSS3】用i标签用作小图标
查看>>
ecshop 网站
查看>>
随机森林(Random Forest)
查看>>
SQL数据库约束
查看>>
当今世界最为经典的十大算法--投票进行时
查看>>
SpringMVC(十六) 处理模型数据之SessionAttributes
查看>>
阅读笔记01
查看>>
mysql设置有外键的主键自增及其他
查看>>