题意如下 有 n 个小朋友参观动物园,动物远的动物包括猫和狗 某个小朋友喜欢猫 就会讨厌狗,反之也一样。
一旦动物园里没有那些被他讨厌的 猫 或 狗 某个小朋友就会开心,但是他喜欢的被去掉就不会开心,问去掉几只动物能让小朋友开心人数最多。输出最多开心的小朋友数。
开始看一下 主要关注点在于被讨厌的那部分,喜欢的我们建立一下匹配关系就好了,那整个二分图构建完毕之后,我们相当于只需要求一下 最大独立集。。但是很显然还有一些矛盾,就是某个小朋友喜欢的可能另外一个小朋友讨厌,所以还不能不去考虑讨厌这种状态的存在,所以我们如果只在人和动物之间建边不合适,我们就在不同小朋友之间建边吧,把小朋友拆成两个点,如果A喜欢的 B 不喜欢,就建立矛盾,之后我们只需要求一下最大匹配(别忘记除2 匹配了两次),就可以求出这个最大独立集了,就求出了最多开心的小朋友数目。
以下是 AC 代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1005;
int ed[maxn][maxn];
bool vis[maxn];
int lin[maxn];
int n,t1,t2;
bool dfs(int s)
{
for(int i=1;i<=n;i++)
{
if(ed[s][i] && !vis[i])
{
vis[i] = true;
if(lin[i] == -1 || dfs(lin[i]))
{
lin[i] = s;
return true;
}
}
}
return false;
}
int mxmatch()
{
int ret = 0;
memset(lin,-1,sizeof(lin));
for(int i=1;i<=n;i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i))
ret ++;
}
return ret / 2;
}
int a[maxn],b[maxn];
int main()
{
char ch1,ch2;
while(~scanf("%d%d%d",&t1,&t2,&n))
{
memset(ed,0,sizeof(ed));
for(int i=1;i<=n;i++)
{
int x,y;
scanf(" %c%d %c%d",&ch1,&x,&ch2,&y);
if(ch1 == 'C')
{
a[i] = x;
b[i] = -y;
}
else
{
a[i] = -x;
b[i] = y;
}
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(a[i] == b[j] || b[i] == a[j])
ed[i][j] = ed[j][i] = 1;
}
printf("%d\n",n - mxmatch());
}
return 0;
}