题目描述:动物园有N只猫,M只狗,P个小孩。每个小孩都有自己喜欢的动物和讨厌的动物,如果他喜欢狗,那么就讨厌猫,
如果他讨厌猫,那么他就喜欢狗。某个小孩能开心,当且仅当他喜欢的动物留在动物园和讨厌的动物不在动物园里面。
现让管理员通过带走某些动物,问最多能使多少个孩子开心。
解题思路:题目有一个关键点,孩子喜欢猫,必然不喜欢狗,反之。 即猫和猫之间,狗和狗之间一定不存在矛盾关系,符合二分图的概念。
如何建立二分图:
若甲小孩喜欢的动物与乙小孩讨厌的动物一样,或者甲小孩讨厌的动物与乙小孩喜欢的动物一样,那甲乙之间就存在着排斥关系,则他们之间连接一条边。
如果他讨厌猫,那么他就喜欢狗。某个小孩能开心,当且仅当他喜欢的动物留在动物园和讨厌的动物不在动物园里面。
现让管理员通过带走某些动物,问最多能使多少个孩子开心。
解题思路:题目有一个关键点,孩子喜欢猫,必然不喜欢狗,反之。 即猫和猫之间,狗和狗之间一定不存在矛盾关系,符合二分图的概念。
如何建立二分图:
若甲小孩喜欢的动物与乙小孩讨厌的动物一样,或者甲小孩讨厌的动物与乙小孩喜欢的动物一样,那甲乙之间就存在着排斥关系,则他们之间连接一条边。
建立完二分图之后,相当于求二分图的最大独立集 = 顶点数 - 最大匹配数。
#include <iostream> #include <cstring> #include <string> #include <algorithm> using namespace std; const int MAXN = 508; struct Child { string like; string dis; }; Child cat[MAXN],dog[MAXN]; int map[MAXN][MAXN]; int link[MAXN]; int used[MAXN]; int cat_num; int dog_num; int dfs(int k) { for(int i=0; i<dog_num; i++) { if(!used[i] && map[k][i]) { used[i] = 1; if(link[i] == -1 || dfs(link[i])) { link[i] = k; return 1; } } } return 0; } int maxMatch() { int cnt = 0; for(int i=0; i<cat_num; i++) { memset(used,0,sizeof(used)); if(dfs(i)) { cnt++; } } return cnt; } int main() { int n,m,p; string a,b; while(cin>>n>>m>>p) { memset(map,0,sizeof(map)); memset(link,-1,sizeof(link)); cat_num = dog_num = 0; while(p--) { cin>>a>>b; //将喜欢猫的孩子划为A子集 if(a[0] == 'C') { cat[cat_num].like = a; cat[cat_num].dis = b; cat_num++; } //将喜欢狗的孩子划为B子集 if(a[0] == 'D') { dog[dog_num].like = a; dog[dog_num].dis = b; dog_num++; } } for(int i=0; i<cat_num; i++) { for(int j=0; j<dog_num; j++) { //若存在排斥关系 if(cat[i].like == dog[j].dis || cat[i].dis == dog[j].like) { map[i][j] = 1; } } } int cnt = maxMatch(); //最大独立集 = 顶点数 - 最大匹配数 cout<<cat_num+dog_num-cnt<<endl; } return 0; }