poj 2771 二分匹配 Guardian of Decency

http://poj.org/problem?id=2771

一个保守的老师带学生出去玩,他希望任何一人不能配成一对,问你K个人中他能带出去的最大人数

 

最大独立集= 顶点数(总人数) - 最大匹配数     

因为最小点覆盖集==最大匹配数

最小点覆盖集: 假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。

因此最大独立集 = 顶点数  -  最小点覆盖集

http://www.matrix67.com/blog/archives/116证明由matrix67给出

  

代码(⊙o⊙)
   
     
#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 ;
}

 

你可能感兴趣的:(poj)