POJ 1904

存一份好一点的强连通模板,主要是数组特别多,要注意初始化!!!不然各种问题,数组越界,值特别大之类的 - -
大致题意:

有n个帅哥要泡n个美女。对于每个帅哥,给出他可以选择的美女序号。然后给出一个可行的匹配。对于每个帅哥,求出他可以选择哪些美女,才能使得所有帅哥都有马子泡。

View Code
#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;
}
原文地址:https://www.cnblogs.com/gray035/p/2971838.html