zoukankan      html  css  js  c++  java
  • BZOJ2744:[HEOI2012]朋友圈(最大团,乱搞)

    Description

    在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着。一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目。
    两个国家看成是AB两国,现在是两个国家的描述:
    1. A国:每个人都有一个友善值,当两个A国人的友善值a、b,如果a xor b mod 2=1,
    那么这两个人都是朋友,否则不是;
    2.B国:每个人都有一个友善值,当两个B国人的友善值a、b,如果a xor b mod 2=0
    或者 (a or b)化成二进制有奇数个1,那么两个人是朋友,否则不是朋友;
    3. A、B两国之间的人也有可能是朋友,数据中将会给出A、B之间“朋友”的情况。
    4.在AB两国,朋友圈的定义:一个朋友圈集合S,满足

    S∈A∪ B,对于所有的i,j∈S,i和j是朋友

    由于落后的古代,没有电脑这个也就成了每年最大的难题,而你能帮他们求出最大朋友圈的人数吗?

    Input

    第一行t<=6,表示输入数据总数。
    接下来t个数据:
    第一行输入三个整数A,B,M,表示A国人数、B国人数、AB两国之间是朋友的对数;第二行A个数ai,表示A国第i个人的友善值;第三行B个数bi,表示B国第j个人的友善值;
    第4——3+M行,每行两个整数(i,j),表示第i个A国人和第j个B国人是朋友。

    Output

    输出t行,每行,输出一个整数,表示最大朋友圈的数目。

    Sample Input

    2 4 7
    1 2
    2 6 5 4
    1 1
    1 2
    1 3
    2 1
    2 2
    2 3
    2 4

    Sample Output

    5
    【样例说明】
    最大朋友圈包含A国第1、2人和B国第1、2、3人。

    HINT

    【数据范围】
    两类数据
    第一类:|A|<=200 |B| <= 200
    第二类:|A| <= 10 |B| <= 3000

    Solution

    $A$了这个题才发现这个题网上怎么清一色匈牙利……QAQ。来一发应该是对的乱搞做法。

    定义权值为奇数的为奇点,偶数的为偶点。首先简单分析一下$A,B$国的性质,可以发现:

    $A$国内的边只有奇点连向偶点,也就是说只看$A$国的话是一个奇-偶的完全二分图。且若答案最大团里含$A$国的人,则奇点最多只有一个,偶点最多只有一个。(因为如果选两个奇点的话这两个奇点中间必定没有边,偶点同理。)

    $B$国内奇点成一个团,偶点成一个团,且$(b_i~or~b_j)$化成二进制有奇数个$1$的也互连。也就是两个团之间连着几条边的形态。

    分析完性质,可以发现$B$国的两个团并不一定是极大团,因为如果两个团之间连着的边足够的话,奇点也是可以被并到偶团里的。那么我们暴力一下,把$B$国的两个团都扩成极大团。

    因为$A$国只有可能被选$0,1,2$个点去和$B$国的两个极大团合并,枚举一下$A$国选哪些就好了。

    注意一些边界条件,具体看代码。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #define N (3009)
     6 using namespace std;
     7 
     8 int n,m,x,y,u,v,ans;
     9 int a[N],b[N],G[N][N];
    10 vector<int>A[2],B[2];
    11 
    12 inline int read()
    13 {
    14     int x=0,w=1; char c=getchar();
    15     while (!isdigit(c)) {if (c=='-') w=-1; c=getchar();}
    16     while (isdigit(c)) x=x*10+c-'0', c=getchar();
    17     return x*w;
    18 }
    19 
    20 int bitcount(int x)
    21 {
    22     return x?bitcount(x>>1)+(x&1):0;
    23 }
    24 
    25 bool check(int x,int opt)
    26 {
    27     bool flag=1;
    28     for (int i=0; i<B[opt].size(); ++i)
    29         if (!G[x][B[opt][i]]) flag=0;
    30     return flag;
    31 }
    32 
    33 int main()
    34 {
    35     x=read(); y=read(); m=read(); n=x+y;
    36     for (int i=1; i<=x; ++i) A[(a[i]=read())%2].push_back(i);
    37     for (int i=1; i<=y; ++i) B[(b[i]=read())%2].push_back(i);
    38     for (int i=1; i<=m; ++i) G[u=read()][v=read()]=G[v][u]=1;
    39     
    40     for (int i=1; i<=y; ++i)
    41     {
    42         int t=b[i]%2, flag=1;
    43         for (int j=0; j<B[t^1].size(); ++j)
    44         {
    45             int tmp=b[B[t^1][j]];
    46             if (tmp%2==(t^1) && bitcount(b[i]|tmp)%2==0) flag=0;
    47         }
    48         if (flag) B[t^1].push_back(i);
    49     }
    50     
    51     ans=max((int)B[0].size(),(int)B[1].size());//只选B国的极大团之一。 
    52     ans=max(ans,(bool)A[0].size()+(bool)A[1].size());//只选A国。 
    53     for (int i=0; i<A[0].size(); ++i)//有一种特殊情况,为A国两个点加B国一个点的团。
    54         for (int j=0; j<A[1].size(); ++j)
    55             for (int k=1; k<=y; ++k)
    56                 if (G[A[0][i]][k] && G[A[1][j]][k]) ans=max(ans,3);
    57                 
    58     for (int i=0; i<A[0].size(); ++i)//选一个A国偶点。 
    59     {
    60          if (check(A[0][i],0)) ans=max(ans,(int)B[0].size()+1);
    61          if (check(A[0][i],1)) ans=max(ans,(int)B[1].size());
    62     }
    63     for (int i=0; i<A[1].size(); ++i)//选一个A国奇点。 
    64     {
    65         if (check(A[1][i],0)) ans=max(ans,(int)B[0].size()+1);
    66         if (check(A[1][i],1)) ans=max(ans,(int)B[1].size()+1);
    67     }
    68     for (int i=0; i<A[0].size(); ++i)//选一个A国偶点和一个A国奇点。 
    69         for (int j=0; j<A[1].size(); ++j)
    70         {
    71             if (check(A[0][i],0) && check(A[1][j],0)) ans=max(ans,(int)B[0].size()+2);
    72             if (check(A[0][i],1) && check(A[1][j],1)) ans=max(ans,(int)B[1].size()+2);
    73         }
    74     printf("%d
    ",ans);
    75 }
  • 相关阅读:
    T-SQL 查询出某个列总值大于X的数据
    ASP.NET 的IP帮助类
    对于一些Http远程连接Api安全的看法;
    老生常谈之SQL Server (行转列,列转行)
    关于SQL2008 “不允许保存更改。您所做的更改要求删除并重新创建以下表。您对无法重新创建的标进行了更改或者启用了‘阻止保存要求重新创建表的更改’” 解决方案
    linq to entity asp.net mvc 多字段排序
    MVC过滤器之添加LoginAttribute,浏览器提示:重定向次数太多
    层级多选框(html+javascript+bootstrap),全层全选和多选
    com.android.internal.os.ZygoteInit$MethodAndArgsCaller 解决
    Andriod Studio adb.exe,start-server' failed -- run manually if necessary 解决
  • 原文地址:https://www.cnblogs.com/refun/p/10438009.html
Copyright © 2011-2022 走看看