这题就是运用到了二分图的三个重要结论之一:
最小点覆盖数: 最小覆盖要求用最少的点(X集合或Y集合的都行)让每条边都至少和其中一个点关联。可以证明:最少的点(即覆盖数)=最大匹配数
最小路径覆盖=最小路径覆盖=|N|-最大匹配数用尽量少的不相交简单路径覆盖有向无环图G的所有结点。解决此类问题可以建立一个二分图模型。把所有顶点i拆成两个:X结点集中的i和Y结点集中的i',如果有边i->j,则在二分图中引入边i->j',设二分图最大匹配为m,则结果就是n-m。
二分图最大独立集=顶点数-二分图最大匹配
在N个点的图G中选出m个点,使这m个点两两之间没有边,求m最大值。
如果图G满足二分图条件,则可以用二分图匹配来做.最大独立集点数 = N - 最大匹配数。
#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
using namespace std;
int head[1505],vis[1505],match[1505];
struct NDOE
{
int to,next;
}edge[100000];
int n,c,ans;
int dfs(int x)
{
int i,to;
for(i=head[x];i!=-1;i=edge[i].next)
{
to=edge[i].to;
if(!vis[to])
{
vis[to]=1;
if(match[to] == -1 || dfs(match[to]))
{
match[to]=x;
return 1;
}
}
}
return 0;
}
int main()
{
while(~scanf("%d",&n))
{
int i,j,k;
int num,a,b;
for(i=0;i<n;i++) head[i]=-1,match[i]=-1;
for(i=0,c=0;i<n;i++)
{
scanf("%d:(%d)",&a,&num);
while(num--)
{
scanf("%d",&b);
edge[c].to=b,edge[c].next=head[a],head[a]=c++;
edge[c].to=a,edge[c].next=head[b],head[b]=c++;
}
}
for(i=0,ans=0;i<n;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
printf("%d\n",ans/2);
}
}