HDU3829 Cat VS Dog(二分图最大独立集)

来源:互联网 发布:知乎的产品流程设计图 编辑:程序博客网 时间:2024/06/15 16:54

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.

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)

Output

For each case, output a single integer: the maximum number of happy
children.

Sample Input

1 1 2C1 D1D1 C11 2 4C1 D1C1 D1C1 D2D2 C1

Sample Output

13

Hint

Case 2: Remove D1 and D2, that makes child 1, 2, 3 happy

思路

动物园有N只猫,M只狗,P个小孩。每个小孩都有自己喜欢的动物和讨厌的动物,如果他喜欢狗,那么就讨厌猫, 如果他讨厌狗,那么他就喜欢猫。某个小孩能开心,当且仅当他喜欢的动物留在动物园和讨厌的动物不在动物园里面。 现让管理员通过带走某些动物,问最多能使多少个孩子开心。

我们对有冲突的人建立双向边,然后求出他们的最大匹配,然后用顶点数n减去有冲突的最大匹配就是答案

为了让尽量多的孩子开心,那么要选出一个最大的集合里面的点没有矛盾,因此根据孩子之间有矛盾建边,然后选出最大独立集即可。

最大独立集=总结点-最大匹配数。因为拿整个二分图来求最大匹配,而不是具体分出X,Y二部分来求,因此最后的匹配数要除以2.

代码

#include<cstdio>#include<cstring>#include<string>#include<set>#include<iostream>#include<stack>#include<queue>#include<vector>#include<algorithm>#define mem(a,b) memset(a,b,sizeof(a))#define inf 0x3f3f3f3f#define mod 10000007#define debug() puts("what the fuck!!!")#define ll long longusing namespace std;const int N=500+20;int vis[N],match[N],e[N][N],n,m,p;pair<string,string>per[N];int dfs(int u){    for(int i=1; i<=p; i++)    {        if(e[u][i]&&!vis[i])        {            vis[i]=1;            if(!match[i]||dfs(match[i]))            {                match[i]=u;                return 1;            }        }    }    return 0;}int query(){    mem(match,0);    int sum=0;    for(int i=1; i<=p; i++)    {        mem(vis,0);        if(dfs(i))sum++;    }    return sum;}int main(){    while(~scanf("%d%d%d",&n,&m,&p))    {        mem(e,0);        for(int i=1; i<=p; i++)        {            cin>>per[i].first>>per[i].second;            for(int j=1; j<i; j++)                if((per[i].first==per[j].second)||(per[i].second==per[j].first))                    e[i][j]=e[j][i]=1;        }        printf("%d\n",p-query()/2);    }    return 0;}