zoukankan      html  css  js  c++  java
  • UVALive 3415 Guardian of Decency(二分图的最大独立集)

    题意:老师在选择一些学生做活动时,为避免学生发生暧昧关系,就提出了四个要求。在他眼中,只要任意两个人符合这四个要求之一,就不可能发生暧昧。现在给出n个学生关于这四个要求的信息,求老师可以挑选出的最大学生数量。

    分析:

      1、这里的问题可以抽象成求最大独立集:若两人发生暧昧,则在两人中建边,当四个条件中任意一个成立,则将两个人孤立。老师选择的学生必然是两两之间不会发生暧昧的。

      公式:最大独立集=顶点总数V-最小点覆盖

      2、这里涉及到离散数学中一些集合的概念,理解起来对在下实属不易,所以就先记住吧。(定义也只是挑重要的记录下来)

      独立集:该集合中的点,两两之间不相邻(没有边)(单独一个点就是独立集)。一个图中含顶点数目最多的独立集称为最大独立集。

      支配集:满足图上任意一个点要么就在集合内,要么也是与集合中的点相邻(顶点集V即是支配集)。一个图中含顶点数最少的支配集称为最小支配集。

      最小点覆盖:当一个点被选入集合,认为与之相连的边都被覆盖了。在能够覆盖所有边的前提下,顶点数最少的集合称为最小点覆盖。

      :与独立集相反,集合中的点两两之间都相邻。一个图中含顶点数最多的团称为最大团。

     性质:

      最大独立集+最小覆盖集=V

      最大团=补图的最大独立集

      最小覆盖集=最大匹配

      3、这里提到了一个最大独立集的样例:http://my.opera.com/IloveLunamaria/blog/show.dml/810972

      其中最赞的一个观点:一般的用二分图匹配解决的问题,都是要证明题目条件等价于“匹配”,就是题目条件等价于“选择一些边,使得每个点都只在一条边中。

      必须明确概念,才去做题目。最大独立集本身与最大匹配无关,是因为其在数学上与最小点覆盖集合互补,又有可以用最大匹配解决最小点覆盖,所以才得出:可以用最大匹配解最大独立集。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<vector>
      5 #include<algorithm>
      6 #define clr(a,m) memset(a,m,sizeof(a))
      7 #define rep(i,a,b) for(int i=a;i<=b;i++)
      8 using namespace std;
      9 
     10 const int MAXN=555;
     11 
     12 struct Person{
     13     int h;
     14     char sex[2],music[111],sport[111];
     15 }p[MAXN];
     16 
     17 int n,ans,man,woman;
     18 
     19 vector<int>G[MAXN];
     20 vector<int>row,col;
     21 
     22 int left[MAXN],right[MAXN],S[MAXN],T[MAXN];
     23 
     24 void init()
     25 {
     26     rep(i,1,n)
     27         G[i].clear();
     28 }
     29 
     30 bool check(int i,int j)
     31 {
     32     if(fabs(p[i].h-p[j].h)>40)return false;
     33     if(strcmp(p[i].sex,p[j].sex)==0)return false;
     34     if(strcmp(p[i].music,p[j].music)!=0)return false;
     35     if(strcmp(p[i].sport,p[j].sport)==0)return false;
     36     return true;
     37 }
     38 
     39 void read()
     40 {
     41     init();
     42     rep(i,1,n)
     43         scanf("%d%s%s%s",&p[i].h,p[i].sex,p[i].music,p[i].sport);
     44     man=1;
     45     rep(i,1,n)
     46         if(p[i].sex[0]=='M'){
     47             woman=1;
     48             rep(j,1,n){
     49                 if(p[j].sex[0]=='F'){
     50                     if(check(i,j))
     51                         G[man].push_back(woman);
     52                     woman++;
     53                 }
     54             }
     55             man++;
     56         }
     57 }
     58 
     59 bool match(int u)
     60 {
     61     S[u]=true;
     62     int sz=G[u].size();
     63     rep(i,0,sz-1){
     64         int v=G[u][i];
     65         if(!T[v]){
     66             T[v]=true;
     67             if(!left[v]||match(left[v])){
     68                 left[v]=u;
     69                 right[u]=v;
     70                 return true;
     71             }
     72         }
     73     }
     74     return false;
     75 }
     76 
     77 void AP()
     78 {
     79     rep(i,1,woman)left[i]=0;
     80     rep(i,1,man)right[i]=0;
     81 
     82     ans=0;
     83     rep(i,1,man){
     84         rep(j,1,man)S[j]=0;
     85         rep(j,1,woman)T[j]=0;
     86         if(match(i))
     87             ans++;
     88     }
     89 }
     90 
     91 void print()
     92 {
     93     printf("%d
    ",n-ans);
     94 }
     95 
     96 int main()
     97 {
     98     int T;
     99     scanf("%d",&T);
    100     while(T--)
    101     {
    102         scanf("%d",&n);
    103         read();
    104         AP();
    105         print();
    106     }
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    面向对象一: 数据加载器完成缓存
    软件开发模式总结
    失业求职随便接个单
    恭喜蓝网5巨头输了
    mysql安装及改端口
    解决NAVICAT 无法连接MYSQL8.0.12_可视化工具无法连接 MYSQL 8.0
    c#截取两个指定字符串中间的字符串
    匹配2关键字得结果
    怎么才能更好伪原创
    AntiCrawlerSolution(反爬解决方案)
  • 原文地址:https://www.cnblogs.com/zstu-abc/p/3297708.html
Copyright © 2011-2022 走看看