http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=137
这题是寻找最大的集合,使得集合中的所有元素都没有关系。用二分图的最大匹配来计算,然后在减去最大的匹配数,就可以得到最大个数。但是如何将集合中元素进行二分,是个比较纠结的事情,开始想以男女来将顶点分为两个集合,但是输入的数据是比较难判断男女关系的。最后上网搜题解的时候,看到直接对所有元素进行一次匹配,然后除以2,就得到了最后的最大匹配情况。到这里我就想明白了,其实对二分图的最大匹配只是寻找最大的独立边的集合,与顶点无关,所以在这里无论是对男生还是对女生进行一次二分匹配,得到的结果都是一样的,故而我们对男生与女生都进行一次二分匹配,得到的结果就是最大匹配的二倍。
代码如下:
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std ;
const int maxn = 505 ;
int map[maxn][maxn] ;
int boy[maxn] ;
int girl[maxn] ;
int mk[maxn] ;
int dfs(int v) ;
int maxmatch() ;
int n ;
int nx ;
int main()
{
int i ;
int j ;
int p ;
int q ;
int k ;
while(scanf("%d" , &n)!=EOF)
{
memset(map , 0 , sizeof(map)) ;
for(i = 1 ; i <= n ; i ++)
{
scanf("%d: (%d)" , &p , &k) ;
for(j = 0 ; j < k ; j ++)
{
scanf("%d" , &q) ;
map[p][q] = 1 ;
}
}
p = maxmatch() ;
printf("%d\n" , n - p/2) ;
}
return 0 ;
}
int maxmatch()
{
int res = 0 ;
memset(boy , -1 , sizeof(boy)) ;
memset(girl ,-1 , sizeof(girl)) ;
for(int i = 0 ; i < n ; i ++ )
{
if(girl[i]==-1)
{
memset(mk , 0 , sizeof(mk)) ;
res += dfs(i) ;
}
}
return res ;
}
int dfs(int v)
{
int u ;
for(u = 0 ; u < n ; u ++)
{
if(map[v][u] && !mk[u])
{
mk[u] = 1 ;
if(boy[u]==-1 || dfs(boy[u]))
{
girl[v] = u ;
boy[u] = v ;
return 1 ;
}
}
}
return 0 ;
}
感觉二分图的匹配最难的不是算法,而是如何将对应的问题化为二分图匹配问题。