poj——1904 King's Quest
Time Limit: 15000MS | Memory Limit: 65536K | |
Total Submissions: 9197 | Accepted: 3370 | |
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.
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.
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
4
2 1 2
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
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
题意:有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚,大臣给出一个匹配表,每个王子都和一个妹子结婚,但是国王不满意,他要求大臣给他另一个表,每个王子可以和几个妹子结婚,按序号升序输出妹子的编号,这个表应满足所有的王子最终都有妹子和他结婚
思路:
这个题我们可以用强连通分量来做,在一个强连通分量里的王子和公主可以结婚。
为什么呢??
我们来想想这样做的正确性。
对于一个王子,他可以喜欢很多的女孩,我们把他们都连上边,而对于女孩,我们只能让他和已经与她匹配的王子连边。(我们姑且这样想好了,在古代的时候嘛,男尊女卑,男的可以有三妻四妾(很正常嘛),而女孩只能从一而终(哼,为什么不是女尊社会啊!!!))
这样我们就可以来求它的强连通分量,在同一个强连通分量里的王子和女孩一定可以结婚。因为你想啊。
初始完美匹配中的丈夫和妻子之间有两条方向不同的边可以互达,则同一个强连通分量中的王子数和妹子数一定是相等的,若王子x可以和另外的一个妹子a结婚,妹子a的原配王子y肯定能找到另外一个妹子b结婚,因为如果找不到的话,则x和a必不在同一个强连通分量中。
所以一个王子可以和所有与他同一强连通分量的妹子结婚,而这不会导致同一强连通分量中的其他王子找不到妹子结婚。
好像又有人要问了:那这样建图啊?!
如果王子u喜欢妹子v,则建一条边u指向v(u,v),对于大臣给出的初始完美匹配,如果王子u和妹子v结婚,则建一条边v指向u(v,u)。建图的时候王子从1~n编号,妹子从n+1~2*n编号。。。。
代码:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 4010 using namespace std; bool vis[N]; int n,m,a,b,tim,tot,sum,top; int dfn[N],low[N],ans[N],head[N],stack[N],belong[N]; struct Edge { int from,to,next; }edge[200000+4000]; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } void output(int x) { if(x/10) output(x/10); putchar(x%10+'0'); }//输出优化。。 void add(int x,int y) { tot++; edge[tot].to=y; edge[tot].next=head[x]; head[x]=tot; } void tarjan(int now) { dfn[now]=low[now]=++tim; stack[++top]=now; vis[now]=true; for(int i=head[now];i;i=edge[i].next) { int t=edge[i].to; if(vis[t]) low[now]=min(low[now],dfn[t]); else if(!dfn[t]) tarjan(t),low[now]=min(low[t],low[now]); } if(low[now]==dfn[now]) { sum++;belong[now]=sum; for(;stack[top]!=now;top--) { belong[stack[top]]=sum; vis[stack[top]]=false; } vis[now]=false;top--; } } int main() { n=read(); for(int i=1;i<=n;i++) { m=read(); while(m--){a=read(),add(i,n+a);} } for(int i=1;i<=n;i++) a=read(),add(a+n,i); for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) { b=0; for(int j=head[i];j;j=edge[j].next) if(belong[i]==belong[edge[j].to]) ans[++b]=edge[j].to-n; sort(ans+1,ans+1+b);//啊啊啊,千万不要忘了sort!!! output(b); for(int j=1;j<=b;j++) { printf(" "); output(ans[j]); } putchar('\n'); } return 0; }
博客借鉴于: