【题目大意】

有两个国家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. Nodejs mac版安装

    Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven ...

  2. hdu 1003 Max Sum (DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 Max Sum Time Limit: 2000/1000 MS (Java/Others)   ...

  3. mysql增删

    create table msg (id int, name varchar(10)); 插入语句 insert into msg values(1,'root'); insert into msg( ...

  4. gcc中的内嵌汇编语言(Intel i386平台)

    [转]http://bbs.chinaunix.net/thread-2149855-1-1.html 一.声明  虽然Linux的核心代码大部分是用C语言编写的,但是不可避免的其中还是有一部分是用汇 ...

  5. OC 01 类和对象

    一.  定义OC的类和创建OC的对象 接下来就在OC中模拟现实生活中的情况,创建一辆车出来.首先要有一个车子类,然后再利用车子类创建车子对象 要描述OC中的类稍微麻烦一点,分2大步骤:类的声明.类的实 ...

  6. 访问WEB-INF目录中的文件

    WEB-INF下面的文件具有安全性,直接在浏览器中输入地址是访问不到的,可以通过servlet来访问. 方法1: 利用<jsp-file>/WEB-INF/a.jsp</jsp-fi ...

  7. mui 选项卡与header文字同步

    mui底部tab固定 头部nav可变 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  8. leetcode 之Rotate Image(8)

    这题需要搞清楚矩阵元素的位置关系,尤其是副对角线元素,沿着副对角线元素 void rotateImage(vector<vector<int>> &matrix) { ...

  9. php性能的问题

    一.影响php性能的常见原因 1.php自身语法使用不当 2.php做了不擅长的时期() 3.php的周边环境(服务器Linux,磁盘:文件存储,数据库,缓存:内存,网络:带宽) 4.php自身的短板 ...

  10. 《java并发编程实战》读书笔记2--对象的共享,可见性,安全发布,线程封闭,不变性

    这章的主要内容是:如何共享和发布对象,从而使它们能够安全地由多个线程同时访问. 内存的可见性 确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化. 上面的程序中NoVisibility可能 ...