这个题需要找到矛盾所在
也就是有的小朋友喜欢某只狗(猫),但是另外一个小朋友却不喜欢这只狗(猫)
那么如何建图呢
考虑到,如果这只狗(猫)不被移除,那么两个小朋友中必有一个小朋友不高兴
所以我们建图可以将有矛盾的两个小朋友建立双向边
(双向边是因为:有矛盾的两个小朋友不可能A高兴能表示B不高兴,但是B不高兴却不能表示A高兴)
然后进行二分图匹配,匹配完找到的是有多少对矛盾的小朋友(但是匹配了两次)
那么除以二就是实际多少对有矛盾,那么总数减去就是最多有多少孩子可以高兴,也就是最大独立集
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
using namespace std;
const int N=500+5;
int n,m,p,sum;
vector<int> Mao[N];
char like[N][5],dislike[N][5];
int vis[N],match[N];
bool dfs(int x)
{
for(int i=0;i<Mao[x].size();i++)
{
int y=Mao[x][i];
if(!vis[y])
{
vis[y]=1;
if(dfs(match[y]) || match[y]==0)
{
match[y]=x;
return true ;
}
}
}
return false ;
}
void ini()
{
for(int i=0;i<=p;i++) Mao[i].clear();
sum=0;
memset(match,0,sizeof(match));
}
int main()
{
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
ini();
for(int i=1;i<=p;i++)
scanf("%s%s",like[i],dislike[i]);//将第i个小朋友喜欢的不喜欢的都存起来
for(int i=1;i<=p;i++)
{
for(int j=1;j<=p;j++)
{
if(strcmp(like[i],dislike[j])==0 || strcmp(dislike[i],like[j])==0)
{//比较两个小朋友是否有矛盾,有就建边
Mao[i].push_back(j);
Mao[j].push_back(i);
}
}
}
for(int x=1;x<=p;x++)
{
memset(vis,0,sizeof(vis));
if(dfs(x)) sum++;
}
printf("%d\n",p-sum/2);
}
return 0;
}