//Cat VS Dog.cpp : 定义控制台应用程序的入口点。
//
/*
题目描述:动物园有N只猫,M只狗,P个小孩。每个小孩都有自己喜欢的动物和讨厌的动物,如果他喜欢狗,那么就讨厌猫,
如果他讨厌猫,那么他就喜欢狗。某个小孩能开心,当且仅当他喜欢的动物留在动物园和讨厌的动物不在动物园里面。
现让管理员通过带走某些动物,问最多能使多少个孩子开心。
解题思路:题目有一个关键点,孩子喜欢猫,必然不喜欢狗,反之。 即猫和猫之间,狗和狗之间一定不存在矛盾关系,符合二分图的概念。
如何建立二分图:
若甲小孩喜欢的动物与乙小孩讨厌的动物一样,或者甲小孩讨厌的动物与乙小孩喜欢的动物一样,那甲乙之间就存在着排斥关系,则他们之间连接一条边。
建立完二分图之后,相当于求二分图的最大独立集 = 顶点数 - 最大匹配数。
*/
#include "stdafx.h"
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int MAXN = 508;
struct Child
{
string like;
string dis;
};
Child cat[MAXN],dog[MAXN];
int map[MAXN][MAXN];
int link[MAXN];
int used[MAXN];
int cat_num;
int dog_num;
int dfs(int k)
{
for(int i=0; i<dog_num; i++)
{
if(!used[i] && map[k][i])
{
used[i] = 1;
if(link[i] == -1 || dfs(link[i]))
{
link[i] = k;
return 1;
}
}
}
return 0;
}
int maxMatch()
{
int cnt = 0;
for(int i=0; i<cat_num; i++)
{
memset(used,0,sizeof(used));
if(dfs(i))
{
cnt++;
}
}
return cnt;
}
int main()
{
int n,m,p;
string a,b;
while(cin>>n>>m>>p)
{
memset(map,0,sizeof(map));
memset(link,-1,sizeof(link));
cat_num = dog_num = 0;
while(p--)
{
cin>>a>>b;
//将喜欢猫的孩子划为A子集
if(a[0] == 'C')
{
cat[cat_num].like = a;
cat[cat_num].dis = b;
cat_num++;
}
//将喜欢狗的孩子划为B子集
if(a[0] == 'D')
{
dog[dog_num].like = a;
dog[dog_num].dis = b;
dog_num++;
}
}
for(int i=0; i<cat_num; i++)
{
for(int j=0; j<dog_num; j++)
{
//若存在排斥关系
if(cat[i].like == dog[j].dis || cat[i].dis == dog[j].like)
{
map[i][j] = 1;
}
}
}
int cnt = maxMatch();
//最大独立集 = 顶点数 - 最大匹配数
cout<<cat_num+dog_num-cnt<<endl;
}
return 0;
}