给出一些狗和猫,及一些人喜欢或讨厌的狗或猫的编号,删去一些猫狗后,能满足最多人喜欢。
建图的时候个人感觉比较难想。。正常(错误)的情况下直接在同一组猫狗直接连一条边了,但其实是对于每一只猫(狗),在喜欢和讨厌它的人之间建边,而且是同时建反向边(因为删去某条被讨厌的够可能获得更大的利益嘛)。最后求最大独立集的时候记得不要忘了除2..因为建了反向边嘛。
#include<stdio.h>
#include<string.h>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 505
int link[N], vis[N];
vector<int> v[N];
int n, m, k;
int like[N], hate[N];
void init()
{
for ( int i = 1; i <= k; i++ )
{
v[i].clear();
}
}
int dfs( int u )
{
for( int i = 0; i < v[u].size(); i++ )
{
int to = v[u][i];
if( !vis[to] )
{
vis[to] = 1;
if( link[to] == -1 || dfs( link[to] ) )
{
link[to] = u;
return 1;
}
}
}
return 0;
}
int main()
{
int tot;
scanf("%d", &tot);
while(tot--)
{
scanf("%d %d %d", &n, &m, &k);
getchar();
init();
char z, x;
int q, w;
for( int i = 1; i <= k; i++ )
{
scanf("%c%d %c%d", &z, &q, &x, &w);
getchar();
if( z == 'C' )
{
like[i] = q + 1000;
}
else
{
like[i] = q + 2000;
}
if( x == 'C' )
{
hate[i] = w + 1000;
}
else
{
hate[i] = w + 2000;
}
}
for ( int i = 1; i <= k; i++ )
{
for( int j = i+1; j <= k; j++ )
{
if(like[i] == hate[j])
{
v[i].push_back(j);
v[j].push_back(i);
}
if(hate[i] == like[j])
{
v[j].push_back(i);
v[i].push_back(j);
}
}
}
memset(link, -1, sizeof(link));
int ans = 0;
for( int i = 1; i <= k; i++ )
{
memset(vis, 0, sizeof(vis));
ans += dfs(i);
}
printf("%d\n", k - ans/2);
}
return 0;
}