POJ1904:King's Quest(强连通 & 二分图)

来源:互联网 发布:千里走单骑知乎 编辑:程序博客网 时间:2024/05/22 12:11

King's Quest
Time Limit: 15000MS Memory Limit: 65536KTotal Submissions: 9296 Accepted: 3413Case 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

Northeastern Europe 2003

题意:N个男,N个女需要结婚,每个男友有自己喜欢的几个女,只能和自己喜欢的某个女结婚,国王下属根据他们的喜欢对象制订了一份结婚列表,但国王不满意,他要求出每个男能够结婚的女,且要求和该女结婚不影响其他所有男结婚。

思路:男喜欢女建边,该结婚列表反向建边,同一个强连通子图里的男可以和女结婚,因为若某男选择和另外一个女仔结婚,那个女仔的未婚夫就要换个未婚妻,依次类推,最终一定会轮回来这个某男的未婚妻,这样显然就是一个强连通,也就是说,只要一个男的和一个女的在一个强连通里,且该男喜欢该女,他们就可以结婚,因为该女可以有其他路径回到该男处,即其他被迫换妻的男都一定能获得新的配偶。顺便这题改用字符输入输出速度直降9秒。

# include <iostream># include <cstdio># include <cstring># include <algorithm>using namespace std;const int maxn = 4008;struct node{    int u, v, next;}edge[maxn*maxn];int dep[maxn], Next[maxn], stk[maxn], in_stk[maxn], low[maxn];int belong[maxn], girl[maxn];int tot, h, cnt, ans;int Scan(){    int res=0,ch,flag=0;    if((ch=getchar())=='-')        flag=1;    else if(ch>='0'&&ch<='9')        res=ch-'0';    while((ch=getchar())>='0'&&ch<='9')        res=res*10+ch-'0';    return flag?-res:res;}void Out(int a){    if(a>9)        Out(a/10);    putchar(a%10+'0');}void add_edge(int u, int v){    edge[tot] = node{u,v,Next[u]};    Next[u] = tot++;}void dfs(int u){    dep[u] = low[u] = ++h;    stk[cnt++] = u;    in_stk[u] = 1;    for(int i=Next[u]; i!=-1; i=edge[i].next)    {        int v = edge[i].v;        if(!dep[v])        {            dfs(v);            low[u] = min(low[u], low[v]);        }        else if(in_stk[v] && dep[v] < low[u])            low[u] = dep[v];    }    if(low[u] == dep[u])    {        int j;        ++ans;        do        {            j = stk[--cnt];            in_stk[j] = 0;            belong[j] = ans;        }while(j != u);    }}int main(){    int n, j;    while(~scanf("%d",&n))    {        tot = h = cnt = ans = 0;        memset(dep, 0, sizeof(dep));        memset(Next, -1, sizeof(Next));        memset(in_stk, 0, sizeof(in_stk));        memset(belong, 0, sizeof(belong));        memset(low, 0, sizeof(low));        for(int i=1; i<=n; ++i)        {            int m, j;            m = Scan();            while(m--)            {                j = Scan();                add_edge(i, j+n);            }        }        for(int i=1; i<=n; ++i)        {            int j;            j = Scan();            add_edge(j+n, i);        }        for(int i=1; i<=2*n; ++i)            if(!dep[i]) dfs(i);        for(int i=1; i<=n; ++i)        {            int sum = 0;            for(int j=Next[i]; j!=-1; j=edge[j].next)            {                int v = edge[j].v;                if(belong[i] == belong[v])                {                    girl[sum++] = v;                }            }            Out(sum);            putchar(' ');            sort(girl, girl+sum);            for(int j=0; j<sum; ++j)            {                Out(girl[j]-n);                if(j == sum-1) putchar('\n');                else putchar(' ');            }        }    }    return 0;}


原创粉丝点击