HDU 3829 Cat VS Dog(最大独立集)
题目大意:
有n只猫,有m只狗。现在有P个学生去参观动物园。每个孩子有喜欢的动物和不喜欢的动物。假如他喜欢猫那么他就一定不喜欢狗(反之亦然)。
如果一个孩子喜欢一个动物,那么这个动物不会被移除,若是不喜欢则移除。现在管理员想知道移除哪些动物可以使最大数量的孩子高兴。
输入数据:
输入包含多组测试实例。
第一行是三个数字n, m, p.
接下来p行。
每行 CX, DX 代表他喜欢第X只猫,讨厌第X只狗(反之亦然)
题目思路:
构图思路:我们把所有人进行构图,如果两个人之间有矛盾就建立一条边。然后求最大独立集就行了
二分图的最大独立集 : 二分图的最大独立集=图的点数 - 最大匹配数
可以这样理解,在总的点集中,去掉最少的点,使得剩下的点相互之间没有边。用最少的点去覆盖所有的边,也就是最小覆盖。
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<queue> #include<cmath> using namespace std; #define INF 0x3fffffff #define maxn 505 int n, m, p, P[maxn], color[maxn];///n只猫 m只狗 p个人 bool G[maxn][maxn], vis[maxn];///构图 vector<vector<int> > LikeDog;///喜欢第k只狗的人邻接表 vector<vector<int> > DisDog;///不喜欢这只够的人的集合 vector<vector<int> > LikeCat;///同上 vector<vector<int> > DisCat; void Init() { LikeDog.clear(); LikeDog.resize(m+1); LikeCat.clear(); LikeCat.resize(n+1); DisDog.clear(); DisDog.resize(m+1); DisCat.clear(); DisCat.resize(n+1); memset(G, false, sizeof(G) ); } void MakeMap() { for(int i=1; i<=m; i++) { int len1 = LikeDog[i].size(); int len2 = DisDog[i].size(); for(int j=0; j<len1; j++) { int v1 = LikeDog[i][j]; for(int k=0; k<len2; k++) { int v2 = DisDog[i][k]; G[v1][v2] = true; G[v2][v1] = true; } } } for(int i=1; i<=n; i++) { int len1 = LikeCat[i].size(); int len2 = DisCat[i].size(); for(int j=0; j<len1; j++) { int v1 = LikeCat[i][j]; for(int k=0; k<len2; k++) { int v2 = DisCat[i][k]; G[v1][v2] = true; G[v2][v1] = true; } } } } bool Find(int u) { for(int i=1; i<=p; i++) { if(!vis[i] && G[u][i]) { vis[i] = true; if(P[i] == -1 || Find(P[i]) ) { P[i] = u; return true; } } } return false; } void DFS(int u,int Color) { color[u] = Color; for(int i=1; i<=p; i++) { if(G[u][i] && !color[i]) { DFS(i, -Color); } } } int solve() { int ans = 0; memset(P, -1, sizeof(P)); memset(color, 0, sizeof(color)); for(int i=1; i<=p; i++) { if(color[i] == 0) DFS(i, 1); } for(int i=1; i<=p; i++) { memset(vis, false, sizeof(vis)); if(color[i] == 1 && Find(i) ) ans ++; } return p - ans; } int main() { while(scanf("%d %d %d ",&n, &m, &p) != EOF) { char ch1, ch2; int a, b; Init(); for(int i=1; i<=p; i++) { scanf("%c%d %c%d",&ch1, &a, &ch2, &b); getchar(); if(ch1 == 'C') { LikeCat[a].push_back(i); DisDog[b].push_back(i); } else { LikeDog[a].push_back(i); DisCat[b].push_back(i); } } MakeMap(); printf("%d\n", solve() ); } return 0; }