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;
}