【题目大意】

有两个国家A和B。存在以下朋友关系:

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是朋友。
求最大的朋友圈的人数。
 
【思路】
这道题求的是最大团。首先将题目大意翻译一下:
1.A国之间,友善值为一奇一偶的为朋友;B国之间,友善值同奇偶性或有(a or b)二进制有奇数个1的为朋友(后面一个条件真没办法翻译,到时候特判一下就好了)。两个之间的直接输入。
2.显然A国至多取出两个人。也就是由三种情况:取0个人、取1个人、取2个人。
3.那么我们就枚举从A国取出来的人,然后再B中删去与那两个人不是朋友的成员①,则只需要单独考虑B中的情况啦!
4.最大团显然是没有办法做的,不妨对B集合取个反图,也就是原来没有边的现在连上,原来有的现在不连。简单来说,就是同奇同偶间不连边,奇偶之间如果满足(a or b)化成二进制有偶数个1就连边。显然是一个二分图!这样问题就转换为最大点独立集。最大点独立集=总数-二分图匹配。
 
【优化】
直接跑Hungary是过不去的。问题在哪里呢?因为一直memset太挫了!
这个时候我们需要用到时钟T1、T2和tim、vis两个数组。还有思路①处的ban数组也注意一下。
到底什么是时间戳呢?好像并没有人解释。弄了一天大致弄出了一个比较清晰的解释:
一般来说匈牙利算法是这样弄得。每次匈牙利算法前将lk数组清空为-1(整个过程中枚举了A中0个1个2个3个人),然后匈牙利算法内部的循环中将vis数组清零。还是这句话——太挫了!!!!
T1在每次枚举开始+1。它用在lk数组上。由于lk数组并没有清空,之前可能已经lk过了,但是事实上每次匈牙利算法,lk是要清空的。所以如果tim[x]的值!=T1,就表示当前这次枚举中这个点还没有连接过,相当于lk[x]=0;如果tim[x]=T1了,说明当前这次已经用过它了,也就是之前清零过了的含义,那么按照朴素的匈牙利来做。
T2则在匈牙利算法中的循环语句中使用,出现在find前,这个是减去vis数组优化的,道理和上面差不多。vis[x]=T2表示当前这次find已经访问过了,而vis[x]!=T2就表示当前没有访问过,相当于vis=0或1。
另外,ban也是一个道理,ban[x]=T1表示当前这次x被ban掉了。
 
综上所述,时间戳并不是像是一些地方所说的一样用来在上一次匈牙利算法的基础上进行增广,而是真的、纯粹地免去memset的过程而已……
再简单点概述,如果有i次操作,每次vis数组都要清空的话,那么第i次操作不如这样转换:!vis[x]→vis[x]!=i,vis[x]→vis[x]=i。
所以上面因为lk数组每次枚举只要清零一次,ban数组也只需要ban一次,所以T1只在三种情况的的开头清空;而vis数组在for循环中每次都要清空,所以同理T2也要一直+1。
哇,其实是一个好简单的东西…………并没有时间戳这个名字来得那么高大上。
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXA=+;
const int MAXB=+;
int na,nb,m;
int a[MAXA],b[MAXB];
bool map[MAXA][MAXB];
vector<int> E[MAXB];
int T1=,T2=,ban[MAXB],tim[MAXB],vis[MAXB],lk[MAXB]; void addedge(int u,int v)
{
E[u].push_back(v);
} int count(int x)
{
int re=;
while (x)
{
re+=x&;
x>>=;
}
return re;
} int find(int x)
{
if (ban[x]==T1)
return ;
for (int i=;i<E[x].size();i++)
{
int to=E[x][i];
if ((ban[to]!=T1) && (vis[to]!=T2))
{
vis[to]=T2;
if (tim[to]!=T1 || !lk[to] || find(lk[to]))
{
tim[to]=T1;
lk[to]=x;
return ;
}
}
}
return ;
} int mis(int x=,int y=)
{
++T1;
int ret=;
for (int i=;i<=nb;i++)
if (map[x][i] || map[y][i]) ban[i]=T1,++ret;
for (int i=;i<=nb;i++)
if (!(b[i]&))
{
++T2;
if (find(i)) ++ret;
}
return (nb-ret);
} void init()
{
memset(map,,sizeof(map));
scanf("%d%d%d",&na,&nb,&m);
for (int i=;i<=na;i++) scanf("%d",&a[i]);
for (int i=;i<=nb;i++) scanf("%d",&b[i]);
for (int i=;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
map[x][y]=;
}
} void solve()
{
for (int i=;i<=nb;i++)
if (!(b[i]&))
for (int j=;j<=nb;j++)
if (b[j]&)
if (!(count(b[i]|b[j])&))
addedge(i,j);
for (int i=;i<=nb;i++) map[][i]=;
int ans=mis();
for (int i=;i<=na;i++)
ans=max(ans,mis(i)+);
for (int i=;i<=na;i++)
if (a[i]&)
for (int j=;j<=na;j++)
if (!(a[j]&))
ans=max(ans,mis(i,j)+);
printf("%d",ans);
} int main()
{
init();
solve();
return ;
}

【最大团转最大点独立集(匈牙利算法+时间戳优化)】BZOJ2744-[HEOI2012]朋友圈的更多相关文章

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

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

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

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

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

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

  4. bzoj 2744 [HEOI2012]朋友圈——补图!+匈牙利算法

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2744 求最大的团<==>补图(有边的变成没边.没边的变成有边)的最大独立集! A ...

  5. 【POJ】1419:Graph Coloring【普通图最大点独立集】【最大团】

    Graph Coloring Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5775   Accepted: 2678   ...

  6. UVALive 6811 Irrigation Line(二分图最小点覆盖--匈牙利算法)

    题意:求最少的线可以覆盖一个由0.1两种数字组成的图中所有的1. eg: 只需要两条线即可. 分析: 1.先为上述例子的行列标号 2.若图中数字为1,则代表该数字所在的行与列有关联. 例如第r1行第c ...

  7. [SCOI2010]连续攻击游戏 匈牙利算法

    觉得题目水的离开 不会匈牙利的请离开 不知道二分图的请离开 不屑的大佬请离开 ……. 感谢您贡献的访问量 ————————————华丽的分割线———————————— 扯淡完了,先重温一下题目 [SC ...

  8. bzoj 1059: [ZJOI2007]矩阵游戏【匈牙利算法】

    注意到怎么换都行,但是如果把某个黑方块用在对角线上,它原来所在的行列的的黑方块就都不能用 所以要选出n组不重的行列组合,这里用匈牙利算法做二分图匹配即可(用了时间戳优化) #include<io ...

  9. 二分图最大匹配(匈牙利算法)简介& Example hdu 1150 Machine Schedule

    二分图匹配(匈牙利算法) 1.一个二分图中的最大匹配数等于这个图中的最小点覆盖数 König定理是一个二分图中很重要的定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数.如果你还不知 ...

随机推荐

  1. 大聊Python----多线程

    Python里的多线程是假的多线程,不管有多少核,同一时间只能在一个核中进行操作!利用Python的多线程,只是利用CPU上下文切换的优势,看上去像是并发,其实只是个单线程,所以说他是假的单线程. 那 ...

  2. Kill windows和linux 进程

    Windows

  3. Spring Boot中配置文件application.properties使用

    一.配置文档配置项的调用 启动后在浏览器直接输入http://localhost:18080/user/test,就直接打印出配置文件中的配置内容. 二.绑定对象bean调用 有时候属性太多了,一个个 ...

  4. windows 上启动appium

    import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecuteResultHandl ...

  5. 常见网络命令之Ping命令

    前言:计算机网络老师要求我们自己总结一下常见的网络命,然后上课可以上去讲一下这些命令使用,像我这么听话的好学生,肯定是照老师要求,认真的总结了一下,总结的过程中,我发现网上已经有的资源讲的都不是很详细 ...

  6. Perl6 Bailador框架(3):路径匹配

    use v6; use Bailador; =begin pod 注意的是, 当/:one设置时 虽然你有/admin或/about, 但这个/:one不会跟现有的匹配 只跟没有的匹配: 也就是说, ...

  7. 以下suse11.3x64可以安装pycrypto-2.6.1

    rpm -qa adaptec-firmware-1.35-2.15.4gnome-menus-branding-SLED-11.1-14.26man-pages-3.15-2.23.1crackli ...

  8. Linux 入门记录:十、Linux 下获取帮助

    一.获取帮助 Linux 提供了极为详细的帮助工具和文档,通过查阅相关文档,可以大大减少需要记忆的东西并提高效率. 二.--help参数 几乎所有命令都可以使用 -h 或 --help 参数获取命令的 ...

  9. 【bzoj4459】JSOI2013丢番图

    某JSOI夏令营出题人啊,naive! 你还是得学习个,搬这种原题不得被我一眼看穿? 求个n^2的约数除以二,向上取整. #include<bits/stdc++.h> using nam ...

  10. mysql分组取前N记录

    http://blog.csdn.net/acmain_chm/article/details/4126306 http://bbs.csdn.net/topics/390958705 1 我只用到了 ...