传送门1
传送门2
思路:
思维不错的一道题。
题意就是给出限制条件,在构建出的图上找最大团,如果是一般图找最大团是NPC问题,所以要转换思路,一看数据范围很像网络流,但是一开始我并没有想到怎么做,也并没有什么比较好的建图方式。
最初的想法就是A国只能选两个(显然),关键在于B国怎么选,B国朋友的限制条件是”或”,所以并不能直接建二分图,绞尽脑汁想了很久也没有什么办法,偷瞄了一眼题解(啪),看到有一句话说要考虑逆问题,直接ctrl+w后继续想,发现如果把B国朋友的限制条件反过来,那么这正是二分图的建图条件,感觉自己还是too young。
把这个瓶颈突破以后,之后的工作就比较容易了,枚举A国0个,1个,2个,然后对B国中符合条件的人分奇偶,建二分图并连边,跑匈牙利或dinic就可以了。
吐槽一下:这个题的数据太水了,我一开始写了一个不清空vis数组的匈牙利得了90分,还发现WA的10分并不是匈牙利的事情,而是我没判断选A国两个人时它们的xor值是否是奇数!判断以后就A了,唉
回到正题,如果每次暴力记录vis的时间戳以及当前点可不可行的话,跑匈牙利是跑不过的(好像只能有70分),学习了一下优化技巧,每次存下来合法的点,然后把图重构一下,这样就可以过剩下的3个点了
设点数为n,边数为m,匈牙利的时间复杂度最坏是O(nm)O(nm),dinic的单位流容量复杂度是O(mn√)O(m\sqrt n)?我的大部分题写的都是dinic,好像只有一两道没法用dinic,只能套匈牙利
提醒一下,并没有什么多组数据,BZOJ和codevs上甚至连数据组数都不用输入
代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
#define inf 1e9
using namespace std;
int T,A,B,M;
int a[205],b[3005],X[3005],Y[3005];
bool ok[205][3005],not_friend[3005][3005];
namespace network
{int s,t,tot,first[3005],dis[3005];queue<int>q;struct edge{int v,w,next;}e[6000005];void init(){memset(first,0,sizeof(first));tot=1;s=0;t=B+1;}void add(int x,int y,int z){e[++tot].v=y;e[tot].w=z;e[tot].next=first[x];first[x]=tot;e[++tot].v=x;e[tot].w=0;e[tot].next=first[y];first[y]=tot;}bool bfs(){memset(dis,0,sizeof(dis));int x;dis[s]=1;for (q.push(s);!q.empty();q.pop()){x=q.front();for (int i=first[x];i;i=e[i].next)if (!dis[e[i].v]&&e[i].w)dis[e[i].v]=dis[x]+1,q.push(e[i].v);}return dis[t]>0;}int dfs(int x,int maxn){if (x==t) return maxn;int used=0,k;for (int i=first[x];i;i=e[i].next)if (dis[e[i].v]==dis[x]+1){k=dfs(e[i].v,min(maxn-used,e[i].w));e[i].w-=k;e[i^1].w+=k;used+=k;if (used==maxn) return maxn;}if (!used) dis[x]=0;return used;}
}
main()
{scanf("%d%d%d",&A,&B,&M);for (int i=1;i<=A;++i) scanf("%d",a+i);for (int i=1;i<=B;++i) scanf("%d",b+i);for (int u,v,i=1;i<=M;++i)scanf("%d%d",&u,&v),ok[u][v]=1;network::init();int tmp,num;for (int i=1;i<=B;++i){for (int j=1;j<i;++j)if ((b[i]^b[j])&1){tmp=(b[i]|b[j]);num=0;for (;tmp;tmp^=tmp&-tmp) ++num;if (num&1);else not_friend[i][j]=not_friend[j][i]=1;}if (b[i]&1) X[++X[0]]=i,network::add(network::s,i,1);else Y[++Y[0]]=i,network::add(i,network::t,1);}for (int i=1;i<=X[0];++i)for (int j=1;j<=Y[0];++j)if (not_friend[X[i]][Y[j]])network::add(X[i],Y[j],1);int ans=B;while (network::bfs()) ans-=network::dfs(network::s,inf);int sum;for (int i=1;i<=A;++i){X[0]=Y[0]=0;network::init();for (int j=1;j<=B;++j){if (ok[i][j])if (b[j]&1) X[++X[0]]=j,network::add(network::s,j,1);else Y[++Y[0]]=j,network::add(j,network::t,1);}sum=X[0]+Y[0]+1;for (int j=1;j<=X[0];++j)for (int k=1;k<=Y[0];++k)if (not_friend[X[j]][Y[k]]) network::add(X[j],Y[k],1);while (network::bfs()) sum-=network::dfs(network::s,inf);ans=max(sum,ans);}for (int i=1;i<=A;++i)for (int j=i+1;j<=A;++j)if ((a[i]^a[j])&1){X[0]=Y[0]=0;network::init();for (int k=1;k<=B;++k){if (ok[i][k]&&ok[j][k])if (b[k]&1) X[++X[0]]=k,network::add(network::s,k,1);else Y[++Y[0]]=k,network::add(k,network::t,1);}sum=X[0]+Y[0]+2;for (int k=1;k<=X[0];++k)for (int l=1;l<=Y[0];++l)if (not_friend[X[k]][Y[l]]) network::add(X[k],Y[l],1);while (network::bfs()) sum-=network::dfs(network::s,inf);ans=max(sum,ans);}printf("%d\n",ans);
}

【BZOJ2744】【codevs2366】朋友圈,二分图最大匹配相关推荐

  1. bzoj2744[HEOI2012]朋友圈

    题目链接:bzoj2744 题目大意: 两个国家看成是AB两国,现在是两个国家的描述: 1.A国:每个人都有一个友善值,当两个A国人的友善值a.b,如果a xor b mod 2=1,那么这两个人都是 ...

  2. BZOJ - 2744 朋友圈 (二分图上的最大团)

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

  3. [HEOI2012] 朋友圈(最大团 + 结论 + 二分图 + 网络流)

    problem luogu-P2423 solution 本题即求无向图最大团问题.这是个 NP hard\text{NP hard}NP hard 问题,所以必须从图的特殊性质出发,否则只能暴搜. ...

  4. 解题报告:luogu P2423 [HEOI2012]朋友圈【最大团转最大点独立集(匈牙利算法+时间戳优化)】

    图的最大团:"任意两点之间都有一条边相连"的子图被称为无向图的团,点数最多的团为图的最大团 朋友圈中任意两个点之间都有关系,既是图中的团. 答案就是图中的最大团. 我们如果把B国的 ...

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

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

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

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

  7. (转)二分图最大匹配的König定理及其证明

    出处:http://www.matrix67.com/blog/archives/116 二分图最大匹配的König定理及其证明 如果你看不清楚第二个字母,下面有一个大号字体版本: 二分图最大匹配的K ...

  8. 【bzoj4443】[Scoi2015]小凸玩矩阵 二分+二分图最大匹配

    题目描述 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的N个数中第K大的数字的最小值是多少. ...

  9. BZOJ1433[ZJOI2009]假期的宿舍——二分图最大匹配

    题目描述 学校放假了······有些同学回家了,而有些同学则有以前的好朋友来探访,那么住宿就是一个问题.比如A 和B都是学校的学生,A要回家,而C来看B,C与A不认识.我们假设每个人只能睡和自己直接认 ...

  10. 【转载】二分图最大匹配的König定理及其证明 Matrix67原创

    二分图最大匹配的König定理及其证明 本文将是这一系列里最短的一篇,因为我只打算把König定理证了,其它的废话一概没有. 以下五个问题我可能会在以后的文章里说,如果你现在很想知道的话,网上去找找答 ...

最新文章

  1. 验证组播的TTL阀值
  2. Android --- 图片的特效处理
  3. PHP两种不同的快递运单号查询
  4. python 没有了matlab的fscanf功能,我该怎么办
  5. 5加载stm32 keil_KEIL 那些编辑技巧与方法
  6. BugkuCTF-Reverse题First_Mobile(xman)
  7. c语言输入字符时控制符%c前加空格的原因解释
  8. 40万亿“新基建”来了!程序员的新翻身机会终于也来了!
  9. SQL SERVER 跨服务器连接
  10. mysql5.7.20官方文档,MySql 5.7.20安装及data和my.ini文件的配置
  11. php properties,PHP ReflectionClass getStaticProperties()用法及代码示例
  12. 3dContactPointAnnotationTool开发日志(八)
  13. hbase windows 单机版安装
  14. ubuntu 中安装 Redis
  15. 字典生成工具 -- pydictor
  16. linux安装ping命令
  17. 代码生成器技术乱弹十一,伽罗华理论与代码生成器
  18. CSS布局的三种方式
  19. PyWiFi 文档说明
  20. GAN动漫人像生成实现(附带源码)

热门文章

  1. 【华为云技术分享】打卡APIG服务专享版,打造全栈API治理方案
  2. 自动驾驶轻松开发?华为云ModelArts赋能智慧出行
  3. 合数分解质数c语言算法,合数分解成质数之和问题探究
  4. linux l字符串,Linux shell 字符串常用操作
  5. Linux单用户下提示权限不够,Linux_/dev/null 权限不足,/dev/null文件设备的权限不对, - phpStudy...
  6. 虚拟机中安装win7
  7. WORD开发工具的控件功能?
  8. quartz.net隔一天执行一次_母乳喂养多久喂一次最好?过度喂养危害大
  9. python random模块
  10. Bootstrap4代码模板