题目
题意:在每一集中,猫和狗都有机会展示自己,然后观众投票决定哪些宠物应该留下来,哪些应该被迫离开。
每个观众都可以对两件事进行投票:一件宠物应该留在节目中,另一件宠物应该被扔出去。此外,基于人人都是爱猫者(即恨狗者)或爱狗者(即恨猫者)这一普遍事实,已决定每一票必须准确说出一只猫和一只狗的名字。
输入
第一行中有一个正数:测试用例的数量,最多100个。在每个测试用例之后:
一行有三个整数c, d, v (≤1 c, d≤100 v和0≤≤500):猫,狗,和选民。
v行,每个行有两个pet标识符。第一个是这个选民想要养的宠物,第二个是这个选民想要扔掉的宠物。宠物标识符以字符“C”或“D”开头,分别表示宠物是猫还是狗。标识符的其余部分是一个整数,给出宠物的数量(猫在1和c之间,狗在1和d之间)。例如,’’ D42’表示狗的数量为42。
输出
每testcase:
其中一行是满足节目要求的选民的最大可能数量。
Sample Input
2
1 1 2
C1 D1
D1 C1
1 2 4
C1 D1
C1 D1
C1 D2
D2 C1
Sample Output
1
3
二分图最大独立集。猫一个集合,狗一个集合。
将 like 这个猫的,hate 这个猫的,连起来。
将 hate 这给狗的,like 这个狗的,连起来。
只要有连起来的边。说明这两个观众的意愿冲突。
二分图的左边内部之间不会有冲突,右边内部之间不会有冲突。
可以很明显的看出来这个题是求一个最大独立集。
#include <cstdio>
#include <cstring>
#define m(a,b) memset(a,b,sizeof a)
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b
using namespace std;
const int N=500+5;
const int INF=0x3f3f3f3f;
int head[N],mt[N];
int vis[N],tot;
struct Edge{int to,nex;}edge[N*N];
struct node{int like,hate;}cat_lover[N],dog_lover[N];
void add(int from,int to)
{
edge[++tot]=(Edge){to,head[from]};head[from]=tot;
}
int find_path(int x)
{
for(int i=head[x];i;i=edge[i].nex)
{
int y=edge[i].to;
if(!vis[y])
{
vis[y]=1;
if(!mt[y]||find_path(mt[y]))
{
mt[y]=x;
return 1;
}
}
}
return 0;
}
int alter(char *str)
{
int x=0,dex=1,len=strlen(str);
while(dex!=len)
{
x+=str[dex]-'0';
x*=10;
dex++;
}
return x/10;
}
int main()
{
int T;
sd(T);
while(T--)
{
m(head,0),m(mt,0);
tot=1;
int n1,n2,m;
scanf("%d%d%d",&n1,&n2,&m);
int cnt1=0,cnt2=0;
for(int i=1;i<=m;i++)
{
char s1[5],s2[5];
scanf("%s%s",s1,s2);
if(s1[0]=='C')
cat_lover[++cnt1]=(node){alter(s1),alter(s2)};
else
dog_lover[++cnt2]=(node){alter(s1),alter(s2)};
}
for(int i=1;i<=cnt1;i++)
for(int j=1;j<=cnt2;j++)
if(dog_lover[j].hate==cat_lover[i].like||dog_lover[j].like==cat_lover[i].hate)
add(i,j); //连边。
int ans=0;
for(int i=1;i<=cnt1;i++)
{
m(vis,0);
if(find_path(i))
ans++;
}
printf("%d\n",m-ans);
}
}