题意

给出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. 1.4.2python网站地图爬虫(每天一更)

    # -*- coding: utf-8 -*- ''' Created on 2019年5月6日 @author: 薛卫卫 ''' import urllib.request import re de ...

  2. Sring 的 @AliasFor 使用规则

    一.该标签存在的意义 顾名思义 @AliasFor 表示别名,它可以注解到自定义注解的两个属性上,表示这两个互为别名,也就是说这两个属性其实同一个含义.该标签存在的含义,从网上查发现有个点, 若  自 ...

  3. Hadoop学习(5)-zookeeper的安装和命令行,java操作

    zookeeper是干嘛的呢 Zookeeper的作用1.可以为客户端管理少量的数据kvkey:是以路径的形式表示的,那就意味着,各key之间有父子关系,比如/ 是顶层key用户建的key只能在/ 下 ...

  4. kube-proxy源码解析

    kubernetes离线安装包,仅需三步 kube-proxy源码解析 ipvs相对于iptables模式具备较高的性能与稳定性, 本文讲以此模式的源码解析为主,如果想去了解iptables模式的原理 ...

  5. pytest

    pytest可以生成多种样式的结果:1.生成JunitXML格式测试报告:命令: --junitxml=path(相对路径)2.生成result log 格式的测试报告: 命令:--resultlog ...

  6. android ——多线程编程

    1.定义一个线程只需要新建一个类继承自Thread.然后重写run()方法,并在里面编写耗时逻辑即可: class MyThread extends Thread{ public void run() ...

  7. Mock Server的搭建

    一.概述 我们系统与第三方开票系统有交互,场景是我们系统请求第三方开票系统,第三方开票系统根据我们的请求数据,生成开票信息然后返回发票号或异常信息,我们根据返回的信息做对应的处理.因为配合上存在一些障 ...

  8. Zookeeper_阅读源码第一步_在 IDE 里启动 zkServer(集群版)

    上篇文章Zookeeper_阅读源码第一步_在 IDE 里启动 zkServer(单机版)讲了在 idea 里以单机的方式启动zookeeper,这篇介绍一下以集群的方式启动. 集群方式启动,才会真正 ...

  9. 对博弈活动中蕴含的信息论原理的讨论,以及从熵角度看不同词素抽象方式在WEBSHELL文本检测中的效果区别

    1. 从赛马说起 0x1:赛马问题场景介绍 假设在一场赛马中有m匹马参赛,令第i匹参赛马获胜的概率为pi,如果第i匹马获胜,那么机会收益为oi比1,即在第i匹马上每投资一美元,如果赢了,会得到oi美元 ...

  10. 自己实现spring核心功能 二

    前言 上一篇我们讲了spring的一些特点并且分析了需要实现哪些功能,已经把准备工作都做完了,这一篇我们开始实现具体功能. 容器加载过程 我们知道,在spring中refesh()方法做了很多初始化的 ...