//目录

LA 3415 保守的老师

题目链接:https://vjudge.net/contest/161820#problem/E

题意:

有一些同学,要从中选出一些同学来,人数尽量多,但是,两两之间要满足至少一个条件(身高差>40,性别相同,。。。)

分析:

最大独立集:尽量选择多的结点,任意两个结点不相邻;

男同学X,女同学Y,如果可能产生关系,连一条边,这样这两个人就不会在一起;

 

最大独立集=n-最大匹配

证明:

最小点覆盖 = 对于每一条边,至少有一个点要被选中

最大独立集 = 对于每一条边,最多一个点被选中

从定义中可以看出,这两个是互补的;

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 500+5;
 6 
 7 struct BPM {
 8     int n,m;
 9     vector<int> G[maxn];
10     int left[maxn];
11     bool T[maxn];
12 
13     int right[maxn];
14     bool S[maxn];
15 
16     void init(int n,int m) {
17         this->n = n;
18         this->m = m;
19         for(int i=0;i<n;i++)
20             G[i].clear();
21     }
22 
23     void AddEdge(int u,int v) {
24         G[u].push_back(v);
25     }
26 
27     bool match(int u) {
28         S[u] = true;
29         for(int i=0;i<G[u].size();i++) {
30             int v = G[u][i];
31             if(!T[v]) {
32                 T[v] = true;
33                 if(left[v]==-1||match(left[v])) {
34                     left[v] = u;
35                     right[u] = v;
36                     return true;
37                 }
38             }
39         }
40         return false;
41     }
42 
43     int solve() {
44         memset(left,-1,sizeof(left));
45         memset(right,-1,sizeof(right));
46         int ans = 0;
47         for(int u=0;u<n;u++) {
48             memset(S,0,sizeof(S));
49             memset(T,0,sizeof(T));
50             if(match(u))
51                 ans++;
52         }
53         return ans;
54     }
55 
56 }sol;
57 
58 struct Student {
59     int h;
60     string music,sport;
61     Student(int h,string music,string sport):h(h),music(music),sport(sport) {}
62 };
63 
64 bool conflict(const Student& a,const Student& b) {
65     return abs(a.h-b.h)<=40&&a.music ==b.music && a.sport!=b.sport;
66 }
67 
68 int main()
69 {
70     int t;
71     cin>>t;
72     while(t--) {
73         int n;
74         cin>>n;
75         vector<Student> male,female;
76         for(int i=0;i<n;i++) {
77             int h;
78             string gender,music,sport;
79             cin>>h>>gender>>music>>sport;
80             if(gender[0]=='M') male.push_back(Student(h,music,sport));
81             else female.push_back(Student(h,music,sport));
82         }
83         int x = male.size();
84         int y = female.size();
85         sol.init(x,y);
86         for(int i=0;i<x;i++)
87             for(int j=0;j<y;j++)
88                 if(conflict(male[i],female[j]))
89                     sol.AddEdge(i,j);
90         printf("%d\n",x+y-sol.solve());
91     }
92     return 0;
93 }
View Code

 

posted @ 2017-05-03 21:41  小草的大树梦  阅读(306)  评论(0编辑  收藏  举报