Cat VS Dog HDU - 3829

16 篇文章 0 订阅
9 篇文章 0 订阅

Cat VS Dog

 HDU - 3829 

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 2
C1 D1
D1 C1

1 2 4
C1 D1
C1 D1
C1 D2
D2 C1

Sample Output

1
3


        
  

Hint

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

题意:

有p个小朋友参观动物园,动物园里面有两种动物,分别为猫和狗。规定一个小朋友喜欢猫就讨厌狗,喜欢狗就讨厌猫。现在管理员要移走一些动物,当然,移走也是有条件的。比如一个小朋友喜欢猫3,讨厌狗4.那么移走了狗4,这个小朋友就会非常开心。同样,如果移走猫3或者没有移走狗4,小朋友就会很不高兴。现在问怎么样才能使开心的小朋友的人数最多。
思路:

先想在狗和猫之间建边,但是不可行,样例就给了提醒,两个小朋友喜欢和讨厌的一模一样,则这么求解会有遗漏。所以可以尝试在小朋友之间进行建边,如果两个小朋友之间存在矛盾则进行建边,即A小朋友喜欢B小朋友讨厌的,或者A小朋友讨厌B小朋友喜欢的。所以就转换成了求解最大独立集值。

将一个点拆成两个点,然后进行求解最大匹配值,小朋友个数p减去匹配数k/2就是答案。


至于为什么拆点建图对,因为所有的矛盾的两个点可以分为两个集合即能构成二分图,如此求解原因解释如下图,和这题异曲同工。所以只有二分图才能有这样的做法,这种做法可以说是二分图的特权。

(图片参考源)

为什么能构成二分图,假设三个点,如下图。

假如A讨厌B喜欢的,如果C和B也矛盾,则C不管喜欢B讨厌的还是C讨厌的B喜欢的,都不会与A造成冲突,同理假设A喜欢B讨厌的,C和B的关系也是如此,因此构成二分图。


--------------------- 
作者:薄层 
来源:CSDN 
原文:https://blog.csdn.net/yo_bc/article/details/75948093 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

题目大意:

有p个小朋友参观动物园,动物园里面有两种动物,分别为猫和狗。规定一个小朋友喜欢猫就讨厌狗,喜欢狗就讨厌猫。

现在管理员要移走0一些动物,当然,移走也是有条件的。比如一个小朋友喜欢猫3,讨厌狗4.那么移走狗4,这个小朋友就会非常开心。同样,如果移走猫3,小朋友就会很不高兴。现在问怎么样才能使开心的小朋友的人数最多。

解题思路:

刚开始想了很久,以为是一道模拟题,类似贪心或者DP什么的,可是始终找不到好的突破点,之后搜了一下,发现是二分图最大独立集。

首先想的是在猫和狗之间建边,但是仔细想想发现,如果有重复的小朋友喜欢、讨厌的都是同一种动物,那么就漏掉了很多小朋友。。这样是不行的。

然后又想了想,发现可以在小朋友之间建边,当然,是在矛盾关系的小朋友之间建边。矛盾有2种情况:我喜欢的是前面讨厌的,我讨厌的是前面喜欢的。

这样,思路就已经很清晰了。

然后就可以套用结论:二分图最大独立集=定点数-二分图最大匹配

但是在做的过程中,我又理解了一点二分图的性质:

因为小朋友与小朋友是没有差别的,而二分图必须要求是2个集合,现在只有一个小朋友的集合,那么我们可以用到拆点的思想,把每个小朋友拆成2个小朋友,这样在求最大匹配的时候除以2就可以了。(相当于匹配了2次~。~)还有一点wa了一下午的地方就是:如果你拆点后,就必须建立双向边,比如1和2之间有矛盾,你不能只建立1-2矛盾边,必须还建立2-1矛盾边。
--------------------- 
作者:飘过的小牛 
来源:CSDN 
原文:https://blog.csdn.net/niushuai666/article/details/7076116 
版权声明:本文为博主原创文章,转载请附上博文链接!

:以每个小朋友为顶点,如果两个小朋友之间有任何一种矛盾就建立他们之间的双向边, 求出最大匹配;

二分图最大独立集=定点数-二分图最大匹配

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
const int N = 555;
int head[N], en;
struct Edge {
	int v, to;
} edge[211111]; 
void addedge(int u, int v) {
	edge[en].v = v;
	edge[en].to = head[u];
	head[u] = en++;
} 
int link[N], in[N];
int dfs(int u) {
	for (int i = head[u]; ~i; i = edge[i].to) {
		int v = edge[i].v;
		if (!in[v]) {
			in[v] = 1;
			if (!link[v] || dfs(link[v])) {
				link[v] = u;
				return 1;
			}
		}
	}
	return 0;
}
int main() {
	
	int n, m, p;
	while (~scanf ("%d %d %d", &n, &m, &p)) {
		
		int b[N], d[N];
		char a[N], c[N];
		memset(head, -1, sizeof(head));
		en = 0;
		for (int i = 1; i <= p; ++i) {
			scanf (" %c%d %c%d", &a[i], &b[i], &c[i], &d[i]);
			for (int j = 1; j < i; ++j) {
				if (a[j] == c[i] && b[j] == d[i] || c[j] == a[i] && d[j] == b[i]) {
					addedge(j, i);
					addedge(i, j);
				}
			}
		}
		memset(link, 0, sizeof(link));
		int ans = 0;
		for (int i = 1; i <= p; ++i) {
			memset(in, 0, sizeof(in));
			if (dfs(i)) ++ans;
		}
		printf ("%d\n", p - ans/2);
	}
	
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值