题目大意:n个王子,每个王子有若干个喜欢的女人。给一个初始完美匹配,让你求另一个表:每个王子的所有可结婚对象,即王子和其某一个可结婚对象匹配后,保证其他王子仍然能够和自己喜欢的某个女人结婚。
建图:王子u喜欢女人v,则u到v连一条边。对于给出的初始完美匹配,王子u与女人v匹配,则v到u连一条边。然后求SCC。
显然对于同一个SCC中王子数目和女人数目是相等的,并且从某个王子出发能够到达所有女人,这样,王子可以和属于同一个SCC中的任意一个女人结婚,而不会影响其他王子。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<stack> using namespace std; #define N 4005 struct Edge{ int v,next; }edge[202005]; int cnt,head[N],dfs_clock,low[N],dfn[N],sccno[N],scc_cnt; stack<int> S; inline void add(int u,int v){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } inline int read(){ char ch; bool flag = false; int a = 0; while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-'))); if(ch != '-'){ a *= 10; a += ch - '0'; } else flag = true; while(((ch = getchar()) >= '0') && (ch <= '9')){ a *= 10; a += ch - '0'; } if(flag) a = -a; return a; } void write(int a){ if(a < 0){putchar('-');a = -a;} if(a >= 10) write(a/10); putchar(a % 10 + '0'); } void dfs(int u){ low[u]=dfn[u]=++dfs_clock; S.push(u); for(int i=head[u];~i;i=edge[i].next){ int v=edge[i].v; if(!dfn[v]){ dfs(v); low[u]=min(low[v],low[u]); } else if(!sccno[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ ++scc_cnt; for(;;){ int x=S.top();S.pop(); sccno[x]=scc_cnt; if(x==u) break; } } } inline void find_scc(int n){ dfs_clock=scc_cnt=0; memset(dfn,0,sizeof(dfn)); memset(sccno,0,sizeof(sccno)); for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i); } int ans[2005]; int main() { int n,k,i,j,x; while(~scanf("%d",&n)){ cnt=0; memset(head,-1,sizeof(head)); for(i=1;i<=n;++i){ k=read(); while(k--){ x=read(); add(i,x+n); } } for(i=1;i<=n;++i){ x=read(); add(x+n,i); } find_scc(n+n); for(i=1;i<=n;++i){ int tot=0; for(j=head[i];~j;j=edge[j].next){ int v=edge[j].v; if(sccno[i]==sccno[v]) ans[tot++]=v-n; } sort(ans,ans+tot); write(tot); for(j=0;j<tot;++j) {putchar(' ');write(ans[j]);} putchar('\n'); } } return 0; }