http://poj.org/problem?id=2771
老师带学生出去旅游,但是担心学生会发生恋爱关系,所以带出去的学生至少要满足以下要求之中的一个:
1.身高相差40cm以上
2.同性
3.喜欢的音乐风格不同
4.喜欢的运动相同
问最多可以带出去多少学生?
个人感觉如果有男有女,就很有可能是二分匹配了。
这道题我们反过来想,如果将所有可能发生恋爱关系的男女配对,那么可以带出去的人数应该等于这个二分图的最大独立集。
根据公式: 最大独立集=顶点数(包括X和Y)-最大匹配
求一次匹配即可。
Source Code
Problem: 2771 | User: 541780774 | |
Memory: 1088K | Time: 579MS | |
Language: G++ | Result: Accepted |
Source Code
#include<stdio.h> #include<stdlib.h> #include<string.h> #include <iostream> using namespace std; int nx, ny; // X的點數目、Y的點數目 int mx[502], my[502]; // X各點的配對對象、Y各點的配對對象 bool vy[502]; // 紀錄Graph Traversal拜訪過的點 bool adj[502][502]; // 精簡過的adjacency matrix // 以DFS建立一棵交錯樹 bool DFS(int x) { for (int y=0; y<ny; ++y) if (adj[x][y] && !vy[y]) { vy[y] = true; // 找到擴充路徑 if (my[y] == -1 || DFS(my[y])) { mx[x] = y; my[y] = x; return true; } } return false; } int bipartite_matching() { // 全部的點初始化為未匹配點。 memset(mx, -1, sizeof(mx)); memset(my, -1, sizeof(my)); // 依序把X中的每一個點作為擴充路徑的端點, // 並嘗試尋找擴充路徑。 int c = 0; for (int x=0; x<nx; ++x) // if (mx[x] == -1) // x為未匹配點,這行可精簡。 { // 開始Graph Traversal memset(vy, false, sizeof(vy)); if (DFS(x)) c++; } return c; } struct{ int hi; char mu[100]; char sp[100]; }p[2][501]; main() { int a,t,ans,n,mm,ff,i,j; char x,y[100],z[100]; scanf("%d",&t); while(t--) { memset(adj,0, sizeof(adj)); scanf("%d",&n); mm=0;ff=0; for(i=0;i<n;i++) { scanf("%d",&a); cin>>x; cin>>y; cin>>z; if(x=='M') { p[0][mm].hi=a; strcpy(p[0][mm].mu,y); strcpy(p[0][mm].sp,z); mm++; } else { p[1][ff].hi=a; strcpy(p[1][ff].mu,y); strcpy(p[1][ff].sp,z); ff++; } } for(i=0;i<mm;i++) for(j=0;j<ff;j++) { if( abs(p[0][i].hi-p[1][j].hi)<=40&&strcmp(p[0][i].mu,p[1][j].mu)==0&&strcmp(p[0][i].sp,p[1][j].sp)!=0) adj[i][j]=1; } nx=mm; ny=ff; printf("%d\n",n-bipartite_matching()); } system("pause"); }