poj/pku 1904(强连通分量解决匹配问题)

来源:互联网 发布:运动保温杯 知乎 编辑:程序博客网 时间:2024/05/26 05:52

题目链接:http://poj.org/problem?id=1904


题意描述:有n个王子和n个美女,每个王子有自己喜欢的美女,保证每个王子都能娶到一个自己喜欢的美女,现在巫师给出了一个王子和美女匹配的方案,但是国王想知道每个王子能够娶到的美女的名单(保证每个王子都能娶到美女)


分析:匹配就是找增广路,假设一个王子i和美女j开始匹配,那么假设王子i要和其他美女匹配,那么美女j必定和其它王子匹配,这里我们连接美女到初始的王子,那么形成的强连通分量里的王子和他喜欢的美女都是可以匹配的


代码: 


//注意在同一个强连通分量中的美女并不是都能和在该连通分量王子匹配//因为有的美女不是王子所喜欢的,所以在同一个强连通分量中找和王子//匹配的美女时只能找王子所喜欢的#include<iostream>#include<cstdio>#include<vector>#include<algorithm>#include<cstring>using namespace std;const int N=4010; //表示点的个数vector<int>g[N];int a[N/2];int low[N],dfn[N],st[N],blg[N],index,top,cnt;bool vis[N];void tarjan(int u){    int v;    low[u]=dfn[u]=index++;    st[++top]=u;    vis[u]=true;    for(int i=0;i<g[u].size();i++)    {        v=g[u][i];        if(dfn[v]==-1)        {            tarjan(v);            if(low[u]>low[v])            low[u]=low[v];        }        else if(low[u]>dfn[v]&&vis[v])low[u]=dfn[v];    }    if(low[u]==dfn[u])    {        cnt++;        int v1;        do        {            v1=st[top];            vis[v1]=false;            blg[v1]=cnt;            top--;        }while(u!=v1);    }}int main (){    int n,i,j,x,num;    while(scanf("%d",&n)!=EOF)    {        for(i=1;i<=2*n;i++)//清空向量        g[i].clear();        for(i=1;i<=n;i++)        {            scanf("%d",&num);            for(j=0;j<num;j++)            {                scanf("%d",&x);                g[i].push_back(x+n);            }        }        for(i=1;i<=n;i++)        {            scanf("%d",&x);            g[x+n].push_back(i);        }        memset(low,0,sizeof(low));        memset(dfn,-1,sizeof(dfn));        memset(blg,0,sizeof(blg));        memset(vis,0,sizeof(vis));        index=1;top=0;cnt=0;        for(i=1;i<=n;i++)        if(dfn[i]==-1)        tarjan(i);        for(i=1;i<=n;i++)        {            int t=0;            for(j=0;j<g[i].size();j++)            if(blg[i]==blg[g[i][j]])            a[t++]=g[i][j]-n;            sort(a,a+t);            printf("%d",t);            for(j=0;j<t;j++)            printf(" %d",a[j]);            printf("\n");        }    }    return 0;}


原创粉丝点击