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 }
  • 相关阅读:
    java io系列23之 BufferedReader(字符缓冲输入流)
    java io系列22之 FileReader和FileWriter
    java io系列21之 InputStreamReader和OutputStreamWriter
    java io系列20之 PipedReader和PipedWriter
    java io系列19之 CharArrayWriter(字符数组输出流)
    java io系列18之 CharArrayReader(字符数组输入流)
    java io系列17之 System.out.println("hello world")原理
    java io系列16之 PrintStream(打印输出流)详解
    java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
    java io系列14之 DataInputStream(数据输入流)的认知、源码和示例
  • 原文地址:https://www.cnblogs.com/refun/p/10438009.html
Copyright © 2011-2022 走看看