http://poj.org/problem?id=2771
一个保守的老师带学生出去玩,他希望任何一人不能配成一对,问你K个人中他能带出去的最大人数
最大独立集= 顶点数(总人数) - 最大匹配数
因为最小点覆盖集==最大匹配数
最小点覆盖集: 假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。
因此最大独立集 = 顶点数 - 最小点覆盖集
http://www.matrix67.com/blog/archives/116证明由matrix67给出
#include " stdio.h "
#include " string.h "
bool map[ 501 ][ 501 ];
int mark[ 501 ];
bool flag[ 501 ];
int k,g,m; // g女的,m男的数量
struct
{
int tall;
char sex;
char music[ 105 ],sport[ 105 ] ;
} boy[ 505 ],girl[ 505 ];
void get_map()
{
int i,x,y,j;
int flag1;
g = m = 0 ;
int tall1;
char sex1,str1[ 105 ],str2[ 105 ];
getchar();
for (i = 0 ;i < k;i ++ )
{
scanf( " %d %c %s%s " , & tall1, & sex1,str1,str2 ) ;
if ( sex1 == ' F ' )
{
girl[ ++ g ].tall = tall1;
girl[ g ].sex = sex1;
strcpy( girl[g].music ,str1 );
strcpy( girl[g].sport ,str2 );
}
else
{
boy[ ++ m ].tall = tall1;
boy[ m ].sex = sex1;
strcpy( boy[m].music ,str1 );
strcpy( boy[m].sport ,str2 );
}
}
for (i = 1 ;i <= g;i ++ )
for (j = 1 ;j <= m;j ++ )
{
flag1 = 1 ;
if ( girl[i].tall - boy[j].tall > 40 || girl[i].tall - boy[j].tall < - 40 )
flag1 = 0 ;
if ( strcmp( girl[i].music ,boy[j].music ) != 0 )
flag1 = 0 ;
if ( strcmp( girl[i].sport , boy[j].sport ) == 0 )
flag1 = 0 ;
if ( flag1 )
map[i][j] = 1 ;
}
}
bool dfs( int x)
{
int i;
for (i = 1 ;i <= m;i ++ )
{
if ( ! map[x][i] || flag[i])
continue ;
flag[i] = 1 ;
if ( ! mark[i] || dfs(mark[i])) // i点为孤立点,或者i不是孤立点时寻找i所对应的女生的增广路,如果那个女生能找到另一条增广路径
{
mark[i] = x; // 就可以使i变成孤立点,从而使增广路径的长度加1,此处的dfs(mark[i])就是找i对应的女生能否有另
return 1 ; // 一条不包含i的增广路径,而mark[]是用来判断是否是孤立点的。
}
}
return 0 ;
}
void solve()
{
int i,count = 0 ;
memset(mark, 0 , sizeof (mark)); // 记录女孩i对应的男孩 //
for (i = 1 ;i <= g;i ++ )
{
memset(flag, 0 , sizeof (flag)); // 标记是否被访问过 //
if (dfs(i))
{
count ++ ;
}
}
printf( " %d\n " ,k - count);
}
int main()
{
int t;
scanf( " %d " , & t);
while ( t -- && scanf( " %d " , & k) != EOF )
{
memset(map, 0 , sizeof (map));
get_map();
solve();
}
return 0 ;
}