标签:ons 最大匹配 cstring 连通 scanf ret iostream size include
建有向图,男生向喜欢的女生建边,女生向国师给的最大匹配的男生建边,因为男生数等于女生数,所以如果可以存在x1娶y2使最大匹配数不变的话,那么x2也可以娶y1,这样就能成环,多对男女也一样
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <stack> using namespace std; const int maxn=4000+100; const int maxm=200000+4000+200;//别忘了女孩还能建反响边到男孩 int low[maxn],dfn[maxn]; int pre[maxn]; int a[maxn]; int nn,cnn; int insk[maxn]; bool vis[maxn]; int n,k; stack<int> sk; int hade[maxm]; struct note { int next; int to; }aa[maxm]; void addage(int fr,int to) { aa[k].to=to; aa[k].next=hade[fr]; hade[fr]=k++; } void tarjan(int u) { nn++; low[u]=dfn[u]=nn; insk[u]=1; vis[u]=1; sk.push(u); for(int i=hade[u];i!=-1;i=aa[i].next) { int v=aa[i].to; if(!vis[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(insk[v]) { low[u]=min(dfn[v],low[u]); } } if(low[u]==dfn[u]) { int v; do { v=sk.top(); sk.pop(); pre[v]=cnn; insk[v]=0; } while(v!=u); cnn++; } } void init() { memset(hade,-1,sizeof(hade)); memset(vis,0,sizeof(vis)); memset(aa,0,sizeof(aa)); while(sk.size()) sk.pop(); memset(insk,0,sizeof(insk)); memset(pre,0,sizeof(pre)); k=0; nn=cnn=0; } int main() { while(~scanf("%d",&n)) { init(); int m,to; for(int i=1;i<=n;i++) { scanf("%d",&m); for(int j=1;j<=m;j++) { scanf("%d",&to); addage(i,to+n); } } for(int i=1;i<=n;i++) { scanf("%d",&to); addage(to+n,i); } for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i); int cnt=0; for(int u=1;u<=n;u++) { for(int i=hade[u];i!=-1;i=aa[i].next)//王子只能娶他喜欢的女生 { int v=aa[i].to; if(pre[v]==pre[u]) a[cnt++]=v-n; } sort(a,a+cnt); printf("%d",cnt); for(int i=0;i<cnt;i++) printf(" %d",a[i]); printf("\n"); cnt=0; } } return 0; }
标签:ons 最大匹配 cstring 连通 scanf ret iostream size include
原文地址:http://www.cnblogs.com/Wangwanxiang/p/7660074.html