存一份好一点的强连通模板,主要是数组特别多,要注意初始化!!!不然各种问题,数组越界,值特别大之类的 - -
大致题意:
有n个帅哥要泡n个美女。对于每个帅哥,给出他可以选择的美女序号。然后给出一个可行的匹配。对于每个帅哥,求出他可以选择哪些美女,才能使得所有帅哥都有马子泡。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <stack> using namespace std; #define Max 4019 #define max(a,b) a>b?a:b struct node{ int u,v,next; }Edge[300000]; stack<int> S; int k,Dindex,Stop,Bcnt,n; int head[Max],DFN[Max],LOW[Max],Belong[Max]; int id[Max],num[Max][Max],top[Max]; bool instack[Max],vis[Max][Max]; void add(int u,int v){ Edge[k].u = u; Edge[k].v = v; Edge[k].next = head[u]; head[u] = k++; } void tarjan(int i) { int j; DFN[i]=LOW[i]=++Dindex; instack[i]=true; S.push(i); for (int w=head[i];w!=-1;w=Edge[w].next) { j=Edge[w].v; if (!DFN[j]) { tarjan(j); if (LOW[j]<LOW[i]) LOW[i]=LOW[j]; } else if (instack[j] && DFN[j]<LOW[i]) LOW[i]=DFN[j]; } if (DFN[i]==LOW[i]) { Bcnt++; do { j=S.top(); S.pop(); instack[j]=false; Belong[j]=Bcnt; } while (j!=i); } } void init() { while(!S.empty()) S.pop(); memset(head,-1,sizeof(head)); memset(DFN,0,sizeof(DFN)); memset(id,0,sizeof(id)); k=Dindex=Stop=Bcnt=0; } int main() { scanf("%d",&n); memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) { int a,b; scanf("%d",&a); while(a--) { scanf("%d",&b); add(i,b+n); vis[i][b+n] = 1; } } for(int i=1;i<=n;i++) { int a; scanf("%d",&a); add(a+n,i); } for(int i=1;i<=2*n;i++) { if(!DFN[i]) tarjan(i); } for(int i=1;i<=n;i++) id[i] = Belong[i]; for(int i=n+1;i<=2*n;i++) { int pos = Belong[i]; top[pos]++; num[pos][top[pos]] = i; } int pt[Max]; int size = 0; for(int i=1;i<=n;i++) { int ans = id[i]; sort(num[ans]+1,num[ans]+top[ans]+1); for(int j=1;j<=top[ans];j++) { if(vis[i][num[ans][j]]) { pt[size++] = num[ans][j]-n; } } printf("%d",size); for(int j=0;j<size;j++) printf(" %d",pt[j]); printf("\n"); size = 0; } return 0; }