题目大意:有N个男的,M个女的,V张投票。每张票的形式要么是Mi Fj,要么是Fi Mj(Mi表示第i个男的,Fi表示第i个女的),第一个出现的表示选取,第二个表示淘汰
问最多能有几张票不存在冲突
解题思路:票分为两个点集,如果冲突了,就连边
最后的答案就是最大独立集了,最大独立集内的所有票都满足条件
#include <cstdio>
#include <cstring>
const int N = 510;
struct Vote{
int mark, elected, out;
Vote() {}
Vote(int mark, int elected, int out): mark(mark), elected(elected), out(out) {}
}V[N];
bool g[N][N], vis[N];
int n, m, v, cas = 1;
int left[N];
void init() {
scanf("%d%d%d", &n, &m, &v);
char v1[10], v2[10];
for (int i = 1; i <= v; i++) {
scanf("%s%s", v1, v2);
int mark, ele = 0, out = 0;
if (v1[0] == 'M') mark = 0;
else mark = 1;
int len = strlen(v1);
for (int j = 1; j < len; j++)
ele = ele * 10 + v1[j] - '0';
len = strlen(v2);
for (int j = 1; j < len; j++)
out = out * 10 + v2[j] - '0';
V[i] = Vote(mark, ele, out);
}
memset(g, 0, sizeof(g));
for (int i = 1; i <= v; i++)
for (int j = i + 1; j <= v; j++) {
if (V[i].mark + V[j].mark == 1) {
if (V[i].out == V[j].elected || V[i].elected == V[j].out) {
g[i][j] = g[j][i] = true;
}
}
}
}
bool dfs(int u) {
for (int i = 1; i <= v; i++) {
if (g[u][i] && !vis[i]) {
vis[i] = true;
if (!left[i] || dfs(left[i])) {
left[i] = u;
return true;
}
}
}
return false;
}
void solve() {
memset(left, 0, sizeof(left));
int ans = 0;
for (int i = 1; i <= v; i++) {
memset(vis, 0, sizeof(vis));
if (dfs(i)) ans++;
}
printf("Case %d: %d\n", cas++, v - ans / 2);
}
int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}