/* Question: give you a bipartite graph. Given the initial exact match, you can determine whether to change the matching object of an X set. The exact match problem still exists: Strong Unicom component, for non-initial matching edges, one-way edges from X to Y are created, and one-way edges from Y to X are reversed. The principle of augmented path is available, non-initial matching edges must be in the same strong Unicom component, you can reconstruct a fully matched */# include <iostream> # include <cstdio> # include <cstring> # include <algorithm> # include <climits> # include <vector> using namespace STD; const int maxv = 4009; int N; struct person {int N; // the outbound degree of X set int Q [2001]; // element in y of the I vector} p [2001]; struct edge {int V, next;} edge [maxv * maxv]; int first [maxv], Li NK [maxv], INS [maxv], dfn [maxv], low [maxv], stack [maxv], SCC [maxv], ANS [maxv]; int e, top, index, num; void add (int u, int v) {edge [e]. V = V; edge [e]. next = first [u]; first [u] = e ++;} void Tarjan (int u) {int V; low [u] = dfn [u] = index ++; stack [++ top] = u; INS [u] = true; // enumerate each edge: u --> V for (int K = first [u]; k! =-1; k = edge [K]. next) {v = edge [K]. v; If (dfn [v] = 0) {Tarjan (V); low [u] = min (low [u], low [v]);} else if (INS [v]) {LOW [u] = min (low [u], dfn [v]);} // If the node u is the root of the strongly connected component if (dfn [u] = low [u]) {num ++; do {v = stack [top --]; INS [v] = false; SCC [v] = num;} while (u! = V) ;}} void solve () {for (INT I = 1; I <= N; I ++) {for (Int J = 0; j <p [I]. n; j ++) {If (link [I]! = P [I]. Q [J] + n) {Add (I, P [I]. Q [J] + n);} else {Add (P [I]. Q [J] + N, I) ;}} memset (dfn, 0, sizeof (dfn); memset (low, 0, sizeof (low )); memset (INS, 0, sizeof (INS); memset (SCC, 0, sizeof (SCC); Index = 1; Top =-1; num = 0; for (INT I = 1; I <= 2 * n; I ++) {If (dfn [I] = 0) {// cout <I <Endl; tarjan (I) ;}} int key = 0; For (INT I = 1; I <= N; I ++) {key = 0; For (Int J = 0; j <p [I]. n; j ++) if (SCC [p [I]. Q [J] + N] = SCC [I]) {ans [Key ++] = P [I]. Q [J];} If (Key = 0) {ans [Key ++] = link [I]-N;} s ORT (ANS, ANS + key); printf ("% d", key); For (INT I = 0; I <key; I ++) {printf ("% d", ANS [I]);} printf ("\ n") ;}} int main () {int TMP, K; while (scanf ("% d", & N )! = EOF) {memset (first,-1, sizeof (first); memset (link,-1, sizeof (Link); E = 0; for (INT I = 1; I <= N; I ++) {scanf ("% d", & P [I]. n); For (Int J = 0; j <p [I]. n; j ++) {scanf ("% d", & P [I]. Q [J]) ;}}for (INT I = 1; I <= N; I ++) {scanf ("% d", & TMP ); link [I] = TMP + N; // initial match of I in X set} solve ();} return 0 ;}