原题链接:​​http://acm.hdu.edu.cn/showproblem.php?pid=2768​


题意:c只猫,d条狗,v个人,每个人都有一个喜欢的猫/狗,讨厌的猫/狗,去掉一个人喜欢的猫/狗,这个人就不高兴,若保留一个人喜欢的猫/狗,那他就高兴。在去掉猫或狗的时候,问最多能使多少人高兴。


思路就是:若两个人喜欢的和讨厌的正好相反,那就把他们连线,最后求他们的最大独立集即可,最大独立集=节点数-最大匹配数。


#define _CRT_SECURE_NO_DEPRECATE 

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<string>
#define INF 99999999;
using namespace std;

int t;
int c, d, v;
int match[505];
bool vis[505];
string like[505];
string dislike[505];
vector<int> vec[505];

int dfs(int u)
{
for (int i = 0; i < vec[u].size(); i++)
{
int v = vec[u][i];
if (!vis[v])
{
vis[v] = 1;
if (match[v] == -1 || dfs(match[v]))
{
match[v] = u;
return 1;
}
}
}
return 0;
}

int hungarian()
{
int ans = 0;
memset(match, -1, sizeof(match));
for (int i = 0; i < v; i++)
{
memset(vis, 0, sizeof(vis));
ans += dfs(i);
}
return ans;
}

int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &c, &d, &v);
for (int i = 0; i < v; i++)
cin >> like[i] >> dislike[i];

for (int i = 0; i < v; i++)
vec[i].clear();

for (int i = 0; i < v; i++)
for (int j = i+1; j < v; j++)
if (like[i] == dislike[j] || dislike[i] == like[j])
{
vec[i].push_back(j);
vec[j].push_back(i);
}

printf("%d\n", v - hungarian() / 2);
}
return 0;
}