刚学了匈牙利算法。匈牙利算法用来求解二分图最大匹配,通过邻接表(邻接矩阵也可以),dfs,就可以做到这点,是个高效的算法。

  最小顶点覆盖:最大匹配/2。

  最小路径覆盖:顶点数-最大匹配。

  POJ1274为模板题。

#include <cstdio>
#include <cstring>
#define FOR(i,x,y) for(int i=x;i<=y;++i)
#define MS(a,b) memset(a,b,sizeof(a))
const int maxx=410;//点的个数
int n,m,k,cnt,u,v,link[maxx],head[maxx];
bool vis[maxx];
struct Edge//邻接表
{
    int to;
    int next;
}edge[maxx*maxx];//表的长度
void add(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
bool dfs(int u)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!vis[v])
        {
            vis[v]=true;
            if(link[v]==-1||dfs(link[v]))
            {
                link[v]=u;
                return true;
            }
        }
    }
    return false;
}
int match()//匹配
{
    int ans=0;
    MS(link,-1);
    FOR(i,1,n)
    {
        MS(vis,0);
        if(dfs(i)) ++ans;
    }
    return ans;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        cnt=0;
        MS(head,-1);
        FOR(u,1,n)
        {
            scanf("%d",&k);
            while(k--)
            {
                scanf("%d",&v);
                add(u,v+n);
            }
        }
        if(m==0) {printf("0\n");continue;}
        printf("%d\n",match());
    }
    return 0;
}