题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3829
题意:有一群人,他们要么喜欢狗讨厌猫,要么喜欢猫讨厌狗,在自己喜欢的动物C留下且自己讨厌的动物D他们会happy,求管理员最多让多少人开心
题解:最大独立点集,拆点转换为最大流问题,当两个人的喜好有矛盾(既自己喜欢的别人讨厌或讨厌的的被人喜欢)建边,为无向图(既A和B有矛盾必然有B和A有矛盾),所以最大独立集=n-最大匹配/2;
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> using namespace std; int n,m,p; struct person{ bool cat; int like; int hate; }pe[550]; int link[550],map[550][550],vis[550]; void init() { memset(map,0,sizeof(map)); for(int i=0;i<p;i++) for(int j=i+1;j<p;j++) { if(pe[i].cat==!pe[j].cat) //判断i,j是否有矛盾,有矛盾则建双向边 { if(pe[i].like==pe[j].hate||pe[i].hate==pe[j].like) { map[i][j]=map[j][i]=1; } } } } int can(int x) { for(int j=0;j<p;j++) { if(!vis[j]&&map[x][j]) { vis[j]=1; if(link[j]==-1||can(link[j])) { link[j]=x; return 1; } } } return 0; } void solve() //二分匹配 { memset(link,-1,sizeof(link)); int num=0; for(int i=0;i<p;i++) { memset(vis,0,sizeof(vis)); if(can(i)) num++; } printf("%d\n",p-num/2); } int main() { while(scanf("%d%d%d",&n,&m,&p)!=EOF) { char ch1,ch2; int aa,bb; for(int i=0;i<p;i++) { cin>>ch1>>aa>>ch2>>bb; if(ch1=='C') { pe[i].cat=true; pe[i].like=aa; pe[i].hate=bb; } else { pe[i].cat=false; pe[i].like=aa; pe[i].hate=bb; } } init(); solve(); } return 0; }