Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 3126 | Accepted: 1308 |
Description
Input
Output
Sample Input
2 4 35 M classicism programming 0 M baroque skiing 43 M baroque chess 30 F baroque soccer 8 27 M romance programming 194 F baroque programming 67 M baroque ping-pong 51 M classicism programming 80 M classicism Paintball 35 M baroque ping-pong 39 F romance ping-pong 110 M romance Paintball
Sample Output
3 7
Source
将所有可以发生恋爱关系的男女进行配对,即将男同学和女同学做为两个顶点集合,如果某一对男女同学能发生恋爱关系,就将二者连接,从而建立二分图,那么可以带的出去的人数应该等于这个二分图的最大独立集.
最大独立集:最大的一个集合,其中的每两点之间都不存在边.
最大独立集=顶点数-最大匹配数.
#include<iostream>
#include<string.h>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
int usedif[501];
//usedif[i]记录Y顶点子集中编号为i的顶点是否使用,注意Y子集中的最多顶点数为(7-1)*12+12=84
int link[501];//link[i]记录与Y顶点子集中编号为i的顶点相连的X顶点子集中x的编号
int mat[501][501];//mat[i][j]表示顶点i与j之间是否有边
int bn,gn;//gx为X顶点子集中的顶点数目,gy为Y顶点子集中的顶点数目
struct People //存储学生信息
{
int h;
char sex;
char mu[105];
char sp[105];
} boy[505],girl[505];
bool can(int t) //判断Y集合中的顶点是否能与X集合中的顶点t匹配
{
int i;
for(i=0;i<gn;i++)
{
if(!usedif[i]&&mat[t][i])
{
usedif[i]=true;
if(link[i]==-1||can(link[i]))
{
link[i]=t;
return true;
}
}
}
return false;
}
int MaxMatch() //求解最大匹配数
{
int i,num=0;
memset(link,-1,sizeof(link));
for(i=0;i<bn;i++)
{
memset(usedif,0,sizeof(usedif));
if(can(i))
num++;
}
return num;
}
int main()
{
int i,j,t,n,ans;
People p;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
bn=gn=ans=0;
for(i=0;i<n;i++)
{
scanf("%d %c %s %s",&p.h,&p.sex,p.mu,p.sp);
if(p.sex=='M')
boy[bn++]=p;
else if(p.sex=='F')
girl[gn++]=p;
}
memset(mat,0,sizeof(mat));
for(i=0;i<bn;i++)
for(j=0;j<gn;j++)
if(abs(boy[i].h-girl[j].h)<=40&&strcmp(boy[i].mu,girl[j].mu)==0&&strcmp(boy[i].sp,girl[j].sp)!=0)
mat[i][j]=true;
ans=n-MaxMatch();
printf("%d/n",ans);
}
return 0;
}