Time Limit: 15000MS | Memory Limit: 65536K | |
Total Submissions: 8460 | Accepted: 3087 | |
Case Time Limit: 2000MS |
Description
Input
Output
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
题意:输入n,表示n个王子,接下来n行,每行首先输入nn,表示王子i喜欢的女子有nn个,然后输入这nn个女子的编号。最后一行输入媒婆已经安排好的配对(都是各自王子喜欢的姑娘)。国王要求在每个儿子都能娶到自己喜欢的姑娘的前提下,每个儿子能够娶的姑娘编号。
思路:由于要输出每个王子能配对的姑娘,所以用二分匹配的思路似乎做不了这题,所以建图的时候让王子先给喜欢的姑娘连边,再在媒婆给出的配对里面让姑娘分别对王子连边,然后缩点,缩完点之后看王子和哪些姑娘在同一个强连通分量里边,如果在一个强连通分量里面直接输出就好。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> #include<stack> using namespace std; typedef long long ll; const int N=4010; struct data { int to,next; } tu[N*100]; int head[N]; int ip; int dfn[N], low[N];///dfn[]表示深搜的步数,low[u]表示u或u的子树能够追溯到的最早的栈中节点的次序号 int sccno[N];///缩点数组,表示某个点对应的缩点值 int step; int scc_cnt;///强连通分量个数 void init() { ip=0; memset(head,-1,sizeof(head)); } void add(int u,int v) { tu[ip].to=v,tu[ip].next=head[u],head[u]=ip++; } vector<int> scc[N];///得出来的缩点,scc[i]里面存i这个缩点具体缩了哪些点 stack<int> S; void dfs(int u) { dfn[u] = low[u] = ++step; S.push(u); for (int i = head[u]; i !=-1; i=tu[i].next) { int v = tu[i].to; if (!dfn[v]) { dfs(v); low[u] = min(low[u], low[v]); } else if (!sccno[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { scc_cnt += 1; scc[scc_cnt].clear(); while(1) { int x = S.top(); S.pop(); if (sccno[x] != scc_cnt) scc[scc_cnt].push_back(x); sccno[x] = scc_cnt; if (x == u) break; } } } void tarjan(int n) { memset(sccno, 0, sizeof(sccno)); memset(dfn, 0, sizeof(dfn)); step = scc_cnt = 0; for (int i = 1; i <=n; i++) if (!dfn[i]) dfs(i); } int main() { int n; while(~scanf("%d",&n)) { init(); for(int i=1; i<=n; i++) { int nn; scanf("%d",&nn); while(nn--) { int t; scanf("%d",&t); add(i,t+n); } } for(int i=1; i<=n; i++) { int t; scanf("%d",&t); add(t+n,i); } tarjan(n*2); for(int i=1; i<=n; i++) { int s[N*10],ans=0; for(int j=head[i]; j!=-1; j=tu[j].next) { int to=tu[j].to; if(sccno[i]==sccno[to]) s[ans++]=to-n; } sort(s,s+ans); printf("%d",ans); for(int i=0; i<ans; i++) printf(" %d",s[i]); puts(""); } } return 0; }