HDU 3829 Cat VS Dog(二分图最大独立集)
http://acm.hdu.edu.cn/showproblem.php?pid=3829
题意:
动物园有N只猫,M只狗,P个小孩。每个小孩都有自己喜欢的动物和讨厌的动物,如果他喜欢狗,那么就讨厌猫,
如果他讨厌猫,那么他就喜欢狗。某个小孩能开心,当且仅当他喜欢的动物留在动物园和讨厌的动物不在动物园里面。
现让管理员通过带走某些动物,问最多能使多少个孩子开心。
分析:
注意想让一个孩子高兴必须同时满足他喜欢的东西留下且他讨厌的东西被抛弃!
我们把所有喜欢狗的孩子放在左边的点集中,所有喜欢猫的孩子放在右边的点集中.
如果左边的小孩i喜欢的狗与右边的小孩j讨厌的狗是同一只的话,那么在左i与右j之间就连一条无向边.
如果左边的小孩i讨厌的猫与右边的小孩j喜欢的猫是同一只的话,那么在左i与右j之间就连一条无向边.
现在管理员要让尽量多的小孩高兴,明显管理员必须想办法选出尽量多的小孩出来,把他们讨厌的动物都抛弃且把他们喜欢的东西都留下才行.注意这些被选出的小孩必须满足:任意两个小孩之间不存在边.因为如果有两个小孩之间存在边,那么说明他们之间有一只动物是一个人喜欢的,另一个人讨厌的.管理员不可能同时满足他们两.
所以现在的问题是:管理员如果在新建的二分图中选出尽量多的点来,使得任意两点之间不存在边. 即最大独立集=n-最大匹配数.
AC代码:
#include<cstdio> #include<cstring> using namespace std; const int maxn= 500+10; struct Max_Match { int n,m; bool g[maxn][maxn]; bool vis[maxn]; int left[maxn]; void init(int n,int m) { this->n=n; this->m=m; memset(g,0,sizeof(g)); memset(left,-1,sizeof(left)); } bool match(int u) { for(int v=1;v<=m;v++)if(g[u][v] && !vis[v]) { vis[v]=true; if(left[v]==-1 || match(left[v])) { left[v]=u; return true; } } return false; } int solve() { int ans=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(match(i)) ans++; } return ans; } }MM; struct Node { int like; int unlike; Node(){} Node(int v1,int v2):like(v1),unlike(v2){} }P1[maxn],P2[maxn]; //分别表示两类小孩 int num1,num2; //两类小孩的数量 int main() { int x1,x2,p; while(scanf("%d%d%d",&x1,&x2,&p)==3) { num1=num2=0; for(int i=1;i<=p;i++) { char c1,c2; int v1,v2; scanf(" %c %d %c %d",&c1,&v1,&c2,&v2); if(c1=='D') P1[++num1]=Node(v1,v2); else if(c1=='C') P2[++num2]=Node(v1,v2); } MM.init(num1,num2); for(int i=1;i<=num1;i++) for(int j=1;j<=num2;j++) { if(P1[i].like == P2[j].unlike || P1[i].unlike == P2[j].like) MM.g[i][j]=true; } printf("%d\n",p-MM.solve()); } return 0; }