题意

给出n个不同的数字\(a_i\),求出最大的子集,使得子集内任意两个数在二进制下至少有两位不同。

题解

先对任意两个二进制位只有一个不同的两个数连边,那么问题就转化成找出最多的点集,任意两点没有边,也就是最大独立集问题。普通的图求最大独立集是N-P困难的,但是二分图求最大独立集合是多项式复杂度的。

所以我们把图转换成二分图形式,把二进制下有奇数个1的数放在左边,有偶数个1的数放在右边,这样左边内的点和右边内的点一定不会有连边,因为两边的点二进制1的个数奇偶性是一样的,且不存在相同的数,那么同一边内的两个数就至少会有两位不同。

接下来就是求二分图的最大独立集,参考博客:二分图的最小顶点覆盖 最大独立集 最大团

简单说就是先用匈牙利求出最大匹配,得到包含在最大匹配内的边,对二分图右边每一个不是最大匹配边的端点的点进行一次dfs,dfs路线是未匹配边->匹配边->未匹配边这样交替,对dfs经过的所有点标记vis。最后二分图左边未标记vis,右边标记了vis的点,就是这张二分图的最大独立集

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int mx = 5005;
const int INF = 0x3f3f3f3f; vector <int> mp[mx];
vector <int> L, R, ans;
int a[mx], linker[mx];
bool used[mx], vis[mx];
int n; bool dfs(int u) {
for (int i = 0; i < mp[u].size(); i++) {
int v = mp[u][i];
if (!used[v]) {
used[v] = true;
if (linker[v] == -1 || dfs(linker[v])) {
linker[v] = u;
return true;
}
}
}
return false;
} int hungary() {
int res = 0;
memset(linker, -1, sizeof(linker));
for (int u = 0; u < L.size(); u++) {
memset(used, false, sizeof(used));
if (dfs(L[u])) res++;
}
return res;
} void dfs2(int u, int flag) {
vis[u] = true;
for (int i = 0; i < mp[u].size(); i++) {
int v = mp[u][i];
if (vis[v]) continue;
if (flag) {
if (linker[u] != v) dfs2(v, flag^1);
} else {
if (linker[v] == u) dfs2(v, flag^1);
}
}
} int main() {
memset(vis, false, sizeof(vis));
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if (__builtin_popcount(a[i]) % 2 == 1) L.push_back(i);
else R.push_back(i);
} for (int i = 0; i < L.size(); i++) {
for (int j = 0; j < R.size(); j++) {
if (__builtin_popcount(a[L[i]]^a[R[j]]) == 1) mp[L[i]].push_back(R[j]), mp[R[j]].push_back(L[i]);
}
}
printf("%d\n", n - hungary());
for (int i = 0; i < R.size(); i++) {
int v = R[i];
//printf("linker[%d] = %d\n", v, linker[v]);
if (linker[v] == -1) dfs2(v, 1);
}
for (int i = 0; i < L.size(); i++)
if (!vis[L[i]]) ans.push_back(L[i]);
for (int i = 0; i < R.size(); i++)
if (vis[R[i]]) ans.push_back(R[i]); for (int i = 0; i < ans.size(); i++) printf("%d%c", a[ans[i]], i==ans.size()-1?'\n':' ');
return 0;
}

F-maximum clique 1_2019牛客暑期多校训练营(第五场)的更多相关文章

  1. 2019牛客暑期多校训练营(第五场) maximum clique 1

    题意:给出n个不相同的数,问选出尽量多的数且任两个数字二进制下不同位数大于等于2. 解法:能想到大于等于2反向思考的话,不难发现这是一个二分图,那么根据原图的最大团等于补图的最大独立点集,此问题就变成 ...

  2. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  3. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  4. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  5. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  6. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

  7. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  8. [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem

    链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...

  9. 2019牛客暑期多校训练营(第三场)- F Planting Trees

    题目链接:https://ac.nowcoder.com/acm/contest/883/F 题意:给定n×n的矩阵,求最大子矩阵使得子矩阵中最大值和最小值的差值<=M. 思路:先看数据大小,注 ...

随机推荐

  1. 关于java飞机躲炮弹的一些对象说明(带源码)

    1.飞机躲炮弹的各种实体类都需要一个画笔将他们画出来 (GameObject) import java.awt.*; public void drawSelf(Graphics g){ g.drawI ...

  2. ubuntu中设置python默认版本

    看/usr/bin中的Python文件,发现该文件是python2.7的链接文件 于是直接删掉这个软链接,然后重新创建python2.6的链接文件: 1 rm /usr/bin/python 2 ln ...

  3. Something wrong with EnCase v8 index search results

    My friend told me that she installed EnCase v8.05 on her workstation which OS version is Win 10. She ...

  4. 有趣的Flex布局

    对于刚接触前端的小白,在还原页面样式的时候,往往会遇到页面布局(layout)上的问题,用着生硬的padding来固定盒子的位置,不仅代码看的沉重,还得适应各种浏览器页面,始终没有办法做到统一.接下来 ...

  5. awk文本处理

    一.前言 (一).awk简介 awk是一种编程语言,用于在linux/unix下对文本和数据进行处理,数据可以来自标准输入.一个或多个文件,或其它命令的输出,它支持用户自定义函数和动态正则表达式等先进 ...

  6. Codeforces 468C Hack it!

    https://www.luogu.org/problemnew/show/CF468C http://codeforces.com/contest/468/problem/C #include &l ...

  7. codeforces1088D_Ehab and another another xor problem交互题

    传送门 一道考验思维的交互题 大致思路就是从最高的二进制位向下询问 代入例子比如: 5 6 6 5 7 4 6 4 讨论一下 交互题的重点学会推理和归纳 #include <bits/stdc+ ...

  8. windwos环境下安装python2和python3

    一 python安装 下载地址: https://www.python.org/downloads/ 环境变量:Path中添加C:\Python27\Scripts\;C:\Python27\; C: ...

  9. 反向传播 Backpropagation

    前向计算:没啥好说的,一层一层套着算就完事了 y = f( ... f( Wlayer2T f( Wlayer1Tx ) ) ) 反向求导:链式法则 单独看一个神经元的计算,z (就是logit)对 ...

  10. Kafka集群配置---Windows版

    Kafka是一种高吞吐量的分布式发布订阅的消息队列系统,Kafka对消息进行保存时是通过tipic进行分组的.今天我们仅实现Kafka集群的配置.理论的抽空在聊 前言 最近研究kafka,发现网上很多 ...