题意:一些男生和一些女生出去旅游,如果任意两个人满足规定的四条之一就可以一起出去玩。问最多可以去多少人。
思路:求一个二分图的最大匹配。然后用总人数减去这个匹配对数就是最大独立点集。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<map>
#include<cstdlib>
#include<string>
using namespace std;
struct node
{
int h,music,sport;
}man[510],woman[510];
int T,t,n,m,num_man,num_woman,tot,link[510][510];
char s[110];
map<string,int> match;
bool vis[510];
int mat[510];
int getnum()
{
int k=match[s];
if(k!=0)
return k;
match[s]=++tot;
return tot;
}
bool dfs(int u)
{
int i,j,k;
for(i=1;i<=num_woman;i++)
if(link[u][i] && !vis[i])
{
vis[i]=1;
if(mat[i]==0 || dfs(mat[i]))
{
mat[i]=u;
return true;
}
}
return false;
}
int main()
{
int i,j,k,h,music,sport,ans;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%d",&n);
num_man=num_woman=tot=0;
match.clear();
for(i=1;i<=n;i++)
{
scanf("%d",&h);
scanf("%s",s);
if(s[0]=='M')
k=0;
else
k=1;
scanf("%s",s);music=getnum();
scanf("%s",s);sport=getnum();
if(k==0)
{
num_man++;
man[num_man].h=h;
man[num_man].music=music;
man[num_man].sport=sport;
}
else
{
num_woman++;
woman[num_woman].h=h;
woman[num_woman].music=music;
woman[num_woman].sport=sport;
}
}
memset(link,0,sizeof(link));
for(i=1;i<=num_man;i++)
for(j=1;j<=num_woman;j++)
if(abs(man[i].h-woman[j].h)>40 || man[i].music!=woman[j].music || man[i].sport==woman[j].sport)
link[i][j]=0;
else
link[i][j]=1;
ans=0;
memset(mat,0,sizeof(mat));
for(i=1;i<=num_man;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
printf("%d\n",n-ans);
}
}