Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 5398 | Accepted: 2269 |
Description
Input
Output
Sample Input
2 4 35 M classicism programming 0 M baroque skiing 43 M baroque chess 30 F baroque soccer 8 27 M romance programming 194 F baroque programming 67 M baroque ping-pong 51 M classicism programming 80 M classicism Paintball 35 M baroque ping-pong 39 F romance ping-pong 110 M romance Paintball
Sample Output
3 7
题意:老师要找一群人漂流,可是老师怕有人谈恋爱,所以找的人之中任何两个人都不能有谈恋爱的趋势,所以给出4个没有谈恋爱趋势的标准,现在让你求老师最多带多少人去漂流。
思路:根据题目意思描述,我们要把和其他人有谈恋爱趋势最多的人找出来,所以相当于一个求最大独立集的过程,首先把有谈恋爱趋势的人连边,连完边直接用二分图跑个最大独立集就ok。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> #include<stack> using namespace std; typedef long long ll; struct data { int h; char sex; char music[110],sport[110]; } x[510]; const int N=510;///两边的最大数量 bool tu[N][N]; int from[N];///记录右边的点如果配对好了它来自哪里 bool use[N];///记录右边的点是否已经完成了配对 int n,m;///m,n分别表示两边的各自数量,n是左边,m是右边 bool dfs(int x) { for(int i=1; i<=m; i++) ///m是右边,所以这里上界是m if(!use[i]&&tu[x][i]) { use[i]=1; if(from[i]==-1||dfs(from[i])) { from[i]=x; return 1; } } return 0; } int hungary() { int tot=0; memset(from,-1,sizeof(from)); for(int i=1; i<=n; i++) ///n是左边,所以这里上界是n { memset(use,0,sizeof(use)); if(dfs(i)) tot++; } return tot; } bool ok(int i,int j) { if(abs(x[i].h-x[j].h)>40) return 1; if(x[i].sex==x[j].sex) return 1; if(strcmp(x[i].music,x[j].music)!=0) return 1; if(strcmp(x[i].sport,x[j].sport)==0) return 1; return 0; } int main() { int t; scanf("%d",&t); while(t--) { memset(tu,0,sizeof(tu)); scanf("%d",&n); m=n; for(int i=1; i<=n; i++) { scanf("%d %c%s%s",&x[i].h,&x[i].sex,x[i].music,x[i].sport); for(int j=1; j<i; j++) if(!ok(i,j)) tu[i][j]=tu[j][i]=1; } printf("%d\n",n-hungary()/2); } return 0; }