uva12083 二分图 求最大独立集 转化为求最大匹配 由题意推出二分图
这题大白书例题 :
Frank 是一个思想有些保守的高中老师,有一次,他需要带一些学生出去旅行,但又怕其中一些学生在旅途中萌生爱意。为了降低这种事情的发生概率,他决定确保带出去的任意两个学生至少要满足下面4条中的一条
1 身高相差大于40
2 性别相同
3 最喜欢的音乐属于不同的类型
4 最喜欢的体育比赛相同
任务帮组Frank挑选尽量多的学生,使得任意两个学生至少满足上述条件中的一条。
解 将不能同时去的人连一条边 就变成求最大独立集,即选择尽量多的节点,使得任意两个节点不相邻。|最大独立集|+|最小顶点覆盖| =|V | 在二分图中 最大匹配为最小顶点覆盖
由于出行中存在男与女 此时可以保证是一个二分图
1 #include <iostream> 2 #include <algorithm> 3 #include <string.h> 4 #include <cstdio> 5 #include <vector> 6 using namespace std; 7 const int maxn =505; 8 struct person{ 9 int num; 10 int high; 11 char male[2]; 12 char love_muc[150]; 13 char love_ty[150]; 14 }P[maxn]; 15 16 struct BPM { 17 int n, m; // 左右顶点个数 18 vector<int> G[maxn]; // 邻接表 19 int left[maxn]; // left[i]为右边第i个点的匹配点编号,-1表示不存在 20 bool T[maxn]; // T[i]为右边第i个点是否已标记 21 int right[maxn]; // 求最小覆盖用 22 bool S[maxn]; // 求最小覆盖用 23 void inti(int n,int m){ 24 this->n =n; this->m=m; 25 for(int i=0; i<n; i++) G[i].clear(); 26 } 27 void add_edg(int u, int v){ 28 G[u].push_back(v); 29 } 30 bool match(int u){ 31 S[u]=true; 32 for(int i=0; i<G[u].size(); i++){ 33 int to = G[u][i]; 34 if(!T[to]){ 35 T[to]=true; 36 if(left[to]==-1||match(left[to])){ 37 left[to]=u; right[u]=to; 38 return true; 39 } 40 } 41 } 42 return false; 43 } 44 int solve(){ 45 memset(left,-1,sizeof(left)); 46 memset(right,-1,sizeof(right)); 47 int ans=0; 48 for(int i=0; i<n; i++){ 49 memset(S,false,sizeof(S)); 50 memset(T,false,sizeof(T)); 51 if(match(i)) ans++; 52 } 53 return ans; 54 } 55 }solver; 56 57 int main() 58 { 59 int cas; 60 scanf("%d",&cas); 61 for(int cc =1; cc<=cas; ++cc){ 62 int n; 63 scanf("%d",&n); 64 int Mnum=0,Fnum=0; 65 for(int i=0; i<n; i++){ 66 scanf("%d%s%s%s",&P[i].high,P[i].male,P[i].love_muc,P[i].love_ty); 67 if(P[i].male[0]=='M') P[i].num=Mnum++; 68 else P[i].num=Fnum++; 69 } 70 solver.inti(Mnum,Fnum); 71 for(int i =0; i<n; i++)if(P[i].male[0]=='M'){ 72 73 for(int j=0; j<n; j++) 74 if( 75 P[j].male[0]=='F'&&abs(P[i].high-P[j].high)<=40 76 &&strcmp(P[i].love_muc,P[j].love_muc)==0&& 77 strcmp(P[i].love_ty,P[j].love_ty)!=0 78 ) solver.add_edg(P[i].num,P[j].num); 79 80 } 81 int ans = solver.solve(); 82 printf("%d\n",n-ans); 83 } 84 return 0; 85 }