题目内容

洛谷链接

在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着。

一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目。两个国家看成是AB两国,现在是两个国家的描述:

\(A\)国:每个人都有一个友善值,当两个\(A\)国人的友善值\(a,b\),如果\(a\text{ xor}\text{ }b \bmod 2=1\),那么这两个人都是朋友,否则不是;

\(B\)国:每个人都有一个友善值,当两个\(B\)国人的友善值\(a,b\),如果\(a\text{ xor}\text{ }b \bmod 2=0\)或者(\(a\text{ or}\text{ }b\))化成二进制有奇数个\(1\),那么两个人是朋友,否则不是朋友;

\(A、B\)两国之间的人也有可能是朋友,数据中将会给出\(A、B\)之间“朋友”的情况。 对于朋友的定义,关系是是双向的。 在AB两国,朋友圈的定义:一个朋友圈集合 \(S\),满足\(S\subset A \cup B\),对于所有的\(i,j \in S\),\(i\)和\(j\)是朋友。

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

输入格式

第一行一个整数\(T(T\leq 6)\),表示输入数据总数。

对于每组数据:

第一行三个整数 \(A,B,M\),分别表示\(A\)国人数,\(B\)国人数,\(AB\)两国之间是朋友的对数。

第二行\(A\)个数\(a_i\)​,表示A国第\(i\)个人的友善值。

第三行\(B\)个数\(b_i\),表示B国第\(i\)个人的友善值。

第\(4\)到第\(3+M\)行,每行两个整数\(x,y\)表示\(A\)国的第\(x\)个人和\(B\)国第\(y\)个人是朋友。

输出格式

输出\(T\)行,每行输出一个整数,表示最大朋友圈的数目。

数据范围

友善值为int类型正整数。

有两类数据:

第一类:\(|A| \leq 200, |B| \leq 200\);

第二类:\(|A| \leq 10, |B| \leq 3000\)。

样例输入

1

2 4 7

1 2

2 6 5 4

1 1

1 2

1 3

2 1

2 2

2 3

2 4

样例输出

5

最大朋友圈包含\(A\)国第\(1,2\)人和\(B\)国第\(1,2,3\)人。

思路

先吐槽:因为按位异或和按位与的优先级调这个破题一下午,谢谢有被恶心到。

此题一看就可知道是一个求最大团的问题,然而一般无向图的求最大团是一个\(NPC\)问题,况且看到其数据范围就可以弃了。所以我们要分析一下其中的性质。

先看\(B\)国,可以看出其为一些奇数点和偶数点,况且其中存在一些连边。是二分图既视感。不过二分图是两边的部点不存在连边,所以我们需要建一个关于\(B\)国的补图。同时补图的最大独立集就是原图的最大团,于是\(B\)国直接建补图跑最大独立集即可。

再看\(A\)国,其要求可理解为选出的人要求两两奇偶不同,所以\(A\)国只能选出\(0、1、2\)人,再看\(B\)国中和这几个人有关系的跑最大独立集,我们直接暴力把所有情况取个\(\max\)即可,记得最大独立集\(=n-\)最大匹配数。

然后你快乐的连边之后一顿非常巨的操作跑匈牙利写完了发现\(T\)了几个点。(然后并不会\(Dinic\)),所以这时候就需要时间戳优化匈牙利。

匈牙利中占了时间效率很大的一块就是memset,每次都要memset理论每次都是\(O(n)\)的效率(当然肯定要小一点),那么每匹配一次都是\(O(n^2m)\)的,这个题要求多次匹配岂不是直接挂了。

所以时间戳优化出现了!其实根本没那么高深,设一个时间戳为\(\text{Clock}\),原来的布尔类型数组就改为整数类型,转化如下:

\[\text{vis}[v]=1\rightarrow \text{vis}[v]=\text{Clock}
\]
\[\text{vis}[v]=0\rightarrow \text{vis}[v]\not=\text{Clock}
\]

每次Clock++,即可\(O(1)\)初始化。

然后就愉快的跑就完事了才不,这个毒瘤出题人居然卡常(可能只有我/kk),跑匈牙利的函数里的那个循环必须加register才能过(大数据居然快了\(\text{200ms}\)),否则卡线\(TLE\)。

其他没啥了。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=3000+10;
const int maxm=2e6+10;
int totA,totB,M,ans=-1;
int a[maxn],b[maxn];
bool g[maxn][maxn]; struct Edge{
int from,to,nxt;
}e[maxm]; inline int read(){
int x=0,fopt=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')fopt=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<3)+(x<<1)+ch-48;
ch=getchar();
}
return x*fopt;
} int head[maxm],cnt;
inline void add(int u,int v){
e[++cnt].from=u;
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
} int Time1,Time2;//时间戳,一个用于vis数组,一个用于标记朋友关系
int vis[maxn],match[maxn],flag[maxn];
bool dfs(int u){
for(register int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(vis[v]!=Time1&&flag[v]==Time2){
vis[v]=Time1;
if(!match[v]||dfs(match[v])){
match[v]=u;
return 1;
}
}
}
return 0;
} inline int Count(int x){//数二进制1的个数
int res=0;
while(x){
if(x&1)res++;
x>>=1;
}
return res;
} inline void SolveA(){
int sum=0;
for(int i=1;i<=totB;i++)
if(b[i]&1){
Time1++;
if(dfs(i))sum++;
}//选0个,直接对B跑匹配
ans=max(ans,totB-sum);
for(int i=1;i<=totA;i++){
int tot=0;sum=0;Time2++;
memset(match,0,sizeof(match));
for(int j=1;j<=totB;j++)
if(g[i][j+totA]){
flag[j]=Time2;tot++;//是朋友则flag[j]=1
}
for(int j=1;j<=totB;j++)
if((b[j]&1)&&flag[j]==Time2){
Time1++;
if(dfs(j))sum++;
}
ans=max(ans,tot-sum+1);//选1个,记得加上选的那个1
}
for(int i=1;i<=totA;i++)
for(int j=i+1;j<=totA;j++){
if((a[i]^a[j])&1){//记得打括号!调了一下午/kk
int tot=0;sum=0;Time2++;
memset(match,0,sizeof(match));
for(int k=1;k<=totB;k++)
if(g[i][k+totA]&&g[j][k+totA]){
flag[k]=Time2;tot++;
}
for(int k=1;k<=totB;k++)
if((b[k]&1)&&flag[k]==Time2){
Time1++;
if(dfs(k))sum++;
}
ans=max(ans,tot-sum+2);//同理,选2个
}
}
} inline void SolveB(){
for(int i=1;i<=totB;i++)
if(b[i]&1){//建补图,即取条件不符合的
for(int j=1;j<=totB;j++){
if(!(b[j]&1)&&!(Count(b[i]|b[j])&1))
add(i,j);
}
}
} int main(){
int T=read();
while(T--){
totA=read(),totB=read(),M=read();
for(int i=1;i<=totA;i++)
a[i]=read();
for(int i=1;i<=totB;i++)
b[i]=read();
SolveB();
for(int i=1;i<=M;i++){
int u=read(),v=read();
g[u][v+totA]=g[v+totA][u]=1;//记录朋友关系
}
SolveA();
printf("%d\n",ans);
}
return 0;
}

【二分图】HEOI2012 朋友圈的更多相关文章

  1. bzoj 2744: [HEOI2012]朋友圈 二分图匹配

    2744: [HEOI2012]朋友圈 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 612  Solved: 174[Submit][Status] ...

  2. 【BZOJ 2744】 2744: [HEOI2012]朋友圈 (最大团,二分图匹配,构图)

    2744: [HEOI2012]朋友圈 Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他 ...

  3. 【BZOJ 2744 】[HEOI2012]朋友圈

    Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最 ...

  4. 【刷题】BZOJ 2744 [HEOI2012]朋友圈

    Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最 ...

  5. luogu P2423 [HEOI2012]朋友圈 (最大团)

    在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着. 一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目.两个国家看成是 ...

  6. BZOJ2744:[HEOI2012]朋友圈(最大团,乱搞)

    Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最 ...

  7. BZOJ2744 HEOI2012朋友圈(二分图匹配)

    先考虑B国.容易发现a xor b mod 2=0即二进制末位相同,那么可以据此将所有人分成两部分,每一部分各自是一个完全图.然后再将a or b有奇数个1的边连上,现在需要求的就是这样一个图里的最大 ...

  8. bzoj2744 [HEOI2012]朋友圈——二分图匹配

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2744 首先,求一个图的最大团等价于求它的补图的最大独立集,而二分图的最大独立集 = 总点数 ...

  9. [HEOI2012]朋友圈

    题目 我们发现我们要求的是一个最大团问题,众所周知这是一个\(NP\)难问题,除了爆搜没有什么别的方法,但是这道题我们可以根据图的特殊性质入手 我们如果把\(B\)国的人分成奇数和偶数两类,就会发现奇 ...

随机推荐

  1. Typora第一次使用

    一级标题 二级标题 三级标题 三个# + 空格 分割线 三个- 三个* 粗体 ctrl + B 斜体 ctrl + I 删除线 引用 一个大于号就可以了 图片: ! + [] + (图片路径) 超链接 ...

  2. IDEA中Javaweb项目图片加载不出来解决方案

    针对IDEA中Javaweb项目中无法加载图片 一.项目的结构及问题介绍 项目结构如下: 在500.jsp页面中访问了img目录下的相关图片,比如背景图片,我在500.jsp中是这样写的路径  bac ...

  3. spring boot 在框架中注入properties文件里的值(Spring三)

    前一篇博客实现了打开第一个页面 链接:https://blog.csdn.net/qq_38175040/article/details/105709758 本篇博客实现在框架中注入propertie ...

  4. xss中shellcode的调用

    shellcode就是利用漏洞所执行的代码 在完整的xss攻击之中,会将shellcode存放在一定的地方,然后触发漏洞,引发shellcode. 1.远程调用执行js 可将js代码单独放在一个js文 ...

  5. pytest文档3-pytest+Allure+jenkins+邮箱发送

    前言: 虽然网上有很多邮件配置的文章,但还是想自己写一下配置的过程,因为在中间也碰到了不同坑.按照这个文档配置的话,99%都可以成功.   一.jenkins 配置邮箱 1.打开jenkins后进入点 ...

  6. [LeetCode] 22. 括号生成(回溯/DP)

    题目 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结果为: [ "((()))", "(()( ...

  7. Java中“==”和 equals的区别

    “==”的作用: 判断两个变量栈内存中存储的值是否相等,如果相等返回true,如果不相等返回false. 有两种形式的比较需要用到比较运算符“==”,一是两个基本数据类型之间的比较,二是两个引用数据类 ...

  8. Vue elelment登录验证 简单版

    http.js import axios from 'axios' import { Message, Loading } from 'element-ui'; import router from ...

  9. 记一次GDB调试

    目标文件: ciscn_2019_ne_5. 来源 :https://buuoj.cn/challenges 保护情况:保护是没有保护的 主要伪代码: int __cdecl main(int arg ...

  10. 微服务实战系列(十)-网关高可用之中间件Keepalived

    1.场景描述 因为要做网关的高可用,用到了keepalived+nginx,来保证nginx的高可用,如下图: 安装了keepavlived,走了一些弯路,记录下吧,nginx的安装就不多说了,博客已 ...