题意:有n个王子,每个王子都有k个喜欢的女生,王子挑选喜欢的女生匹配,然后再给你n个王子最开始就定好的匹配,每个王子输出能够结合且不影响其他王子的女生匹配
解题思路:强连通缩点,每个王子与其喜欢的女生连接一条边,然后n个匹配的女生与对应的王子连接一条边,这样,如果有部分王子和女生在同一强连通分量内,说明这些王子和女生是能够互换的(渣男)
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<queue> #include<cstdio> #include<set> using namespace std; const int maxn=4040; struct Edge { int next;int to; }edge[maxn*100]; int scc_cnt,step,index,cnt,ans,n,k,x,y; int low[maxn],dfn[maxn],visit[maxn],head[maxn],sccno[maxn],instack[maxn],flag[maxn]; vector<int>scc[maxn]; void add(int u,int v) { edge[cnt].next=head[u];edge[cnt].to=v;head[u]=cnt++; } void tarjan(int u) { low[u]=dfn[u]=++step; instack[++index]=u; visit[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(visit[v]==1) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { scc_cnt++; scc[scc_cnt].clear(); do { scc[scc_cnt].push_back(instack[index]); sccno[instack[index]]=scc_cnt; visit[instack[index]]=0; index--; } while(u!=instack[index+1]); } return; } void init() { memset(head,-1,sizeof(head)); cnt=step=index=scc_cnt=0; memset(visit,0,sizeof(visit)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); } int main() { while(scanf("%d",&n)!=EOF) { init(); for(int i=1;i<=n;i++) { scanf("%d",&k); for(int j=1;j<=k;j++) { scanf("%d",&x); flag[x+n]=i; add(i,x+n); } } for(int i=1;i<=n;i++) { scanf("%d",&x); add(x+n,i); } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) { int s[maxn*10],ans=0; for(int j=head[i];j!=-1;j=edge[j].next) { int v=edge[j].to; if(sccno[i]==sccno[v]) s[ans++]=v-n; } sort(s,s+ans); printf("%d",ans); for(int i=0;i<ans;i++) printf(" %d",s[i]); printf("\n"); } } }