hdu4685

题解:

二分图匹配

对于每一个单身狗

见一个虚拟的人

然后就可以做了

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2000;
const int M=1000000+3000;
struct EDGE{int v,next;}edge[M];
int first[N],low[N],dfn[N],sta[M],belong[N];
int ans[N],match[N],flag[N];
bool instack[N],vis[N];
int n,m,g,cnt,top,scc,maxn;
int Scan()  
{
    int res=0,ch,flag=0;
    if ((ch=getchar())=='-')
        flag=1;
    else if (ch>='0'&&ch<='9')
        res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
    return flag?-res:res;
}
void Out(int a)
{
    if (a>9)
        Out(a/10);
    putchar(a%10+'0');
}
void AddEdge(int u,int v)
{
    edge[g].v=v;
    edge[g].next=first[u];
    first[u]=g++;
}
int min(int a,int b)
{
    return a<b?a:b;
}
int max(int a,int b)
{
    return a>b?a:b;
}
void init()
{
    g=cnt=top=scc=0;
    memset(first,-1,sizeof(first));
    memset(dfn,0,sizeof(dfn));
    memset(instack,0,sizeof(instack));
    memset(flag,0,sizeof(flag));
    n=Scan();
    m=Scan();
    maxn=max(n,m);   
}
bool dfs(int u)
{
    int i,v;
    for (i=first[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if (!vis[v])
        {
            vis[v]=1;
            if (match[v]==0||dfs(match[v]))
            {
                match[v]=u;
                flag[u]=v;
                return 1;
            }
        }
    }
    return 0;
}
void xiong()   
{
    int i;
    memset(match,0,sizeof(match));
    for (i=1;i<=maxn;i++)
    {
        memset(vis,0,sizeof(vis));
        dfs(i);
    }
}
void Tarjan(int u)
{
    low[u]=dfn[u]=++cnt;
    sta[++top]=u;
    instack[u]=1;
    for (int i=first[u];i!=-1;i=edge[i].next)
     {
        int v=edge[i].v;
        if (!dfn[v])
         {
            Tarjan(v);
            low[u]=min(low[u],low[v]);
         }
        else if (instack[v])low[u]=min(low[u],dfn[v]);
     }
    if (low[u]==dfn[u])
    {
        scc++;
        while (1)
         {
            int v=sta[top--];
            instack[v]=0;
            belong[v]=scc;
            if (u==v)
                break;
         }
     }
}
void build()
{
    int i,k,v,j;
    for (i=1;i<=n;i++)
    {
        k=Scan();
        while(k--)
        {
            v=Scan();
            AddEdge(i,v+maxn);   
        }
    }
    xiong();  
    int all=2*maxn;
    for (i=1;i<=maxn;i++)   
    {
        if (!flag[i])
        {
            all++;
            for (j=1;j<=maxn;j++) 
                AddEdge(j,all);
            match[all]=i;
            flag[i]=all;
        }
    }

    for (i=maxn+1;i<=2*maxn;i++)  
    {
        if (!match[i])
        {
            all++;
            for (j=maxn+1;j<=2*maxn;j++) 
                AddEdge(all,j);
            flag[all]=i;
            match[i]=all;
        }
    }
    for (i=1;i<=all;i++)  
     if (flag[i])AddEdge(flag[i],i);
}
void solve()
{
    int i,u,v;
    for (i=1;i<=maxn;i++) 
     if (!dfn[i])Tarjan(i);
    for (u=1;u<=n;u++)
    {
        int count=0;
        for (i=first[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if (belong[u]==belong[v])
            {
                if (v-maxn>m)
                    continue;
                ans[count++]=v-maxn;
            }
        }
        sort(ans,ans+count);
        Out(count);
        for (i=0;i<count;i++)
         {
            putchar(' ');
            Out(ans[i]);
         } 
        putchar('
');
     }
}
int main()
{
    int t=Scan();
    for (int cas=1;cas<=t;cas++)
     {
        init();
        build();
        printf("Case #%d:
",cas);
        solve();
     }
    return 0;
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8270414.html