有p个小朋友参观动物园,动物园里面有两种动物,分别为猫和狗。规定一个小朋友喜欢猫就讨厌狗,喜欢狗就讨厌猫。
现在管理员要移走0一些动物,当然,移走也是有条件的。比如一个小朋友喜欢猫3,讨厌狗4.那么移走狗4,这个小朋友就会非常开心。同样,如果移走猫3,小朋友就会很不高兴。现在问怎么样才能使开心的小朋友的人数最多。
解题思路:
刚开始想了很久,以为是一道模拟题,类似贪心或者DP什么的,可是始终找不到好的突破点,之后搜了一下,发现是二分图最大独立集。
首先想的是在猫和狗之间建边,但是仔细想想发现,如果有重复的小朋友喜欢、讨厌的都是同一种动物,那么就漏掉了很多小朋友。。这样是不行的。
然后又想了想,发现可以在小朋友之间建边,当然,是在矛盾关系的小朋友之间建边。矛盾有2种情况:我喜欢的是前面讨厌的,我讨厌的是前面喜欢的。
这样,思路就已经很清晰了。
然后就可以套用结论:二分图最大独立集=定点数-二分图最大匹配
但是在做的过程中,我又理解了一点二分图的性质:
因为小朋友与小朋友是没有差别的,而二分图必须要求是2个集合,现在只有一个小朋友的集合,那么我们可以用到拆点的思想,把每个小朋友拆成2个小朋友,这样在求最大匹配的时候除以2就可以了。(相当于匹配了2次~。~)还有一点wa了一下午的地方就是:如果你拆点后,就必须建立双向边,比如1和2之间有矛盾,你不能只建立1-2矛盾边,必须还建立2-1矛盾边。
Cat VS Dog
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others)Total Submission(s): 1723 Accepted Submission(s): 581
Problem Description
The zoo have N cats and M dogs, today there are P children visiting the zoo, each child has a like-animal and a dislike-animal, if the child's like-animal is a cat, then his/hers dislike-animal must be a dog, and vice versa.
Now the zoo administrator is removing some animals, if one child's like-animal is not removed and his/hers dislike-animal is removed, he/she will be happy. So the administrator wants to know which animals he should remove to make maximum number of happy children.
Now the zoo administrator is removing some animals, if one child's like-animal is not removed and his/hers dislike-animal is removed, he/she will be happy. So the administrator wants to know which animals he should remove to make maximum number of happy children.
Input
The input file contains multiple test cases, for each case, the first line contains three integers N <= 100, M <= 100 and P <= 500.
Next P lines, each line contains a child's like-animal and dislike-animal, C for cat and D for dog. (See sample for details)
Next P lines, each line contains a child's like-animal and dislike-animal, C for cat and D for dog. (See sample for details)
Output
For each case, output a single integer: the maximum number of happy children.
Sample Input
1 1 2 C1 D1 D1 C1 1 2 4 C1 D1 C1 D1 C1 D2 D2 C1
Sample Output
1 3
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 510
#define N 250010
int Head[M] , Next[N] , Key[N];
int match[M];
string like[M] , dislike[M];
bool visit[M];
int num , child;
void add( int u, int v )
{
Key[num] = v;
Next[num] = Head[u];
Head[u] = num++;
}
bool find( int u )
{
int temp;
for( int i=Head[u] ; i != -1 ; i=Next[i] )
{
temp = Key[i];
if( !visit[temp] )
{
visit[temp] = true;
if( match[temp] == -1 || find(match[temp]) )
{
match[temp] = u;
return true;
}
}
}
return false;
}
int hungary( )
{
int sum = 0 ;
for( int i=0 ; i<child ; i++ )
{
memset( visit , false , sizeof(visit) );
if( find(i) )
sum++;
}
return sum;
}
int main( )
{
int cat , dog;
string likeit , dislikeit;
while( scanf("%d%d%d",&cat,&dog,&child) != EOF )
{
num = 0;
memset( Head , -1 , sizeof(Head) );
memset( match , -1 , sizeof(match) );
for( int i=0 ; i<child ; i++ )
{
cin >> likeit >> dislikeit;
like[i] = likeit;
dislike[i] = dislikeit;
}
for( int i=0 ; i<child ; i++ )
{
for( int j=0 ; j<child ; j++ )
if( like[i].compare(dislike[j]) ==0 || dislike[i].compare(like[j]) ==0 )
add( i,j );
}
printf("%d\n",child-hungary()/2);
}
return 0 ;
}