HDU-3829 Cat VS Dog(最大独立集)

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就是答案。

 
 
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
const int N = 505;
vector<int>G[N];
int c[105],d[105];
int vis[N],match[N];
int n,m,p;
void init(){
	for(int i=0;i<=p;i++) 
	   G[i].clear();
}
int Find(int x){
	for(int i=0;i<G[x].size();i++){
		int u=G[x][i];
		if(!vis[u]){
			vis[u]=1;
			if(match[u]==-1||Find(match[u])){
				match[u]=x;
				return 1;
			}
		}
	}
	return 0;
}
int solve(){
	memset(match,-1,sizeof(match));
	int ans=0;
	for(int i=0;i<p;i++){
		memset(vis,0,sizeof(vis));
		ans+=Find(i);
	}
	return ans;
}
int main(){
	while(scanf("%d%d%d",&n,&m,&p)!=EOF){
		init();
		for(int i=0;i<p;i++){
			char s[N][2][5];
			scanf("%s%s",s[i][0],s[i][1]);
			for(int j=0;j<i;j++){
				if(!strcmp(s[i][0],s[j][1])){
					G[i].push_back(j);
					G[j].push_back(i);
				}
				if(!strcmp(s[i][1],s[j][0])){
					G[i].push_back(j);
					G[j].push_back(i);
				}
			}
		}
		int ans=solve();
		printf("%d\n",p-ans/2);
	}
	return 0;
} 

 代码二:
#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<iostream>
using namespace std;
const int N = 505;
int n,m,t;
string like[N],dislike[N];
vector<int>G[N];
int match[N],vis[N];
void init(){
	for(int i=0;i<N;i++)
	   G[i].clear();
}
void Creat(int x){
	for(int i=1;i<x;i++){
		if(dislike[i]==like[x]||dislike[x]==like[i]){
			G[x].push_back(i);
			G[i].push_back(x);
		} 
	}
}
int Find(int u){
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		if(!vis[v]){
			vis[v]=1;
			if(match[v]==-1||Find(match[v])){
				match[v]=u;
				return 1;
			}
		}
	}
	return 0;
}
void MaxMatch(){
	memset(match,-1,sizeof(match));
	int ans=0;
    for(int i=1;i<=t;i++){
    	memset(vis,0,sizeof(vis));
    	ans+=Find(i);
    }
    printf("%d\n",t-ans/2);
}
int main(){
	while(scanf("%d%d%d",&n,&m,&t)!=EOF){
		init();
		for(int i=1;i<=t;i++){
			cin>>like[i]>>dislike[i];
			Creat(i);
		}
		MaxMatch();
	}
	return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值