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

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2744

求最大的团<==>补图(有边的变成没边、没边的变成有边)的最大独立集!

A国的奇数和偶数变成两个团,B国变成一个二分图,A国和B国之间还有一些任意的边。

B国的部分肯定是求最大独立集。A国呢?A、B国的选点会互相影响。

其实枚举A国的选点情况就行了!每次把相关的B国点删掉,跑匈牙利。

观察数据范围,还专门分成两部分,一看就是一些复杂度在A国点上、一些复杂度在B国点上嘛!

思路。要敢于想补图。要能想到一些稍微暴力一点的方法,如枚举,而不是钻研如何权衡A国B国的选点情况什么的(==要回算时间复杂度)。

1A还是极好的。

时间复杂度玄学。不过匈牙利原来是边越多跑得越快呀。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=205,M=3005;
int T,n,m,c,pos[N],cos[M],b[M],hd[N],xnt,p0,p1,c0,c1,ans,cnt,per[M];
bool bf[M][M],af[N][M],qx[M],vis[M];
struct Ed{
  int nxt,to;Ed(int n=0,int t=0):nxt(n),to(t) {}
}ed[N*M];
void add(int x,int y)
{
  ed[++xnt]=Ed(hd[x],y);hd[x]=xnt;
}
bool check(int i,int j)
{
  int k=(b[i]|b[j]),ct=0;
  while(k)k-=(k&-k),ct++;
  return ct&1;
}
bool dfs(int a)
{
  for(int i=c1;i<=m;i++)
    if(bf[a][i]&&!qx[i]&&!vis[i])
      {
    vis[i]=1;
    if(!per[i]||dfs(per[i]))
      {
        per[i]=a;return true;
      }
      }
  return false;
}
int xyl()
{
  int ret=0;memset(per,0,sizeof per);
  for(int i=1;i<=c0;i++)
    if(!qx[i]){
      memset(vis,0,sizeof vis);
      if(dfs(i))ret++;
    }
  return ret;
}
void solve()
{
  for(int i=1;i<=p0;i++)
    for(int j=p1;j<=n;j++)
      {
    memset(qx,0,sizeof qx);
    for(int k=hd[i];k;k=ed[k].nxt)qx[ed[k].to]=1;
    for(int k=hd[j];k;k=ed[k].nxt)qx[ed[k].to]=1;
    cnt=0;for(int i=1;i<=m;i++)if(!qx[i])cnt++;
    cnt-=xyl();ans=max(ans,cnt+2);
      }
  for(int i=1;i<=n;i++)
    {
      memset(qx,0,sizeof qx);
      for(int k=hd[i];k;k=ed[k].nxt)qx[ed[k].to]=1;
      cnt=0;for(int i=1;i<=m;i++)if(!qx[i])cnt++;
      cnt-=xyl();ans=max(ans,cnt+1);
    }
  memset(qx,0,sizeof qx);cnt=m;
  cnt-=xyl();ans=max(ans,cnt);
}
int main()
{
//  scanf("%d",&T);
//  while(T--)
//    {
      memset(hd,0,sizeof hd);xnt=0;ans=0;
      memset(bf,true,sizeof bf);memset(af,0,sizeof af);
      scanf("%d%d%d",&n,&m,&c);p0=0;p1=n+1;int x,y;
      for(int i=1;i<=n;i++)
    {
      scanf("%d",&x);
      if(x&1)pos[i]=++p0;
      else pos[i]=--p1;
    }
      c0=0;c1=m+1;
      for(int i=1;i<=m;i++)
    {
      scanf("%d",&b[i]);
      if(b[i]&1)cos[i]=++c0;
      else cos[i]=--c1;
      for(int j=1;j<i;j++)
        if(check(i,j))bf[cos[i]][cos[j]]=bf[cos[j]][cos[i]]=0;
    }
      while(c--)
    {
      scanf("%d%d",&x,&y);
      af[pos[x]][cos[y]]=1;
    }
      for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
      if(!af[i][j])add(i,j);
      solve();printf("%d\n",ans);
//    }
  return 0;
}

原文地址:https://www.cnblogs.com/Narh/p/9280714.html

时间: 2025-01-01 05:44:23

bzoj 2744 [HEOI2012]朋友圈——补图!+匈牙利算法的相关文章

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

2744: [HEOI2012]朋友圈 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 612  Solved: 174[Submit][Status][Discuss] Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目. 两个国家看成是AB两国,现在是两个国家的描述: 1.         

bzoj 2744: [HEOI2012]朋友圈

1 #include<cstdio> 2 #include<iostream> 3 #define M 3010 4 using namespace std; 5 int A,B,m,a[M],b[M],map[M][M],head[M],next[M*M>>2],u[M*M>>2],cnt,ans,f1,f2,ban[M],f[M],k[M],pi[M]; 6 int ji(int a1) 7 { 8 int sum=0; 9 for(;a1;) 10 {

【BZOJ 2744 】[HEOI2012]朋友圈

Description 在很久很久以前,曾经有两个国家和睦相处,无忧无虑的生活着.一年一度的评比大会开始了,作为和平的两国,一个朋友圈数量最多的永远都是最值得他人的尊敬,所以现在就是需要你求朋友圈的最大数目. 两个国家看成是AB两国,现在是两个国家的描述: 1.         A国:每个人都有一个友善值,当两个A国人的友善值a.b,如果a xor b mod 2=1, 那么这两个人都是朋友,否则不是: 2.         B国:每个人都有一个友善值,当两个B国人的友善值a.b,如果a xor

BZOJ 3168 Heoi2013 钙铁锌硒维生素 矩阵求逆+匈牙利算法

题目大意:给定一个n?n的满秩矩阵A和一个n?n的矩阵B.求一个字典序最小的1...n的排列a满足将随意一个Ai换成Bai后矩阵A仍然满秩 我们考虑建立一个二分图.假设Ai能换成Bj.就在i?>j之间连接一条边 那么这个图怎么建呢? 考虑一个行向量Bi,我们在A中找到最小的行向量集合满足Bi能够被这些行向量线性表出,那么显然Bi仅仅能替换这些行向量 我们能够设矩阵C满足C?A=B,那么C=B?A?1 Ci,j≠0表示Bi的线性表出须要Aj,因此CT就是这个二分图的邻接矩阵 如今我们有了一个二分图

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

注意到怎么换都行,但是如果把某个黑方块用在对角线上,它原来所在的行列的的黑方块就都不能用 所以要选出n组不重的行列组合,这里用匈牙利算法做二分图匹配即可(用了时间戳优化) #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=405; int T,n,cnt,h[N],lk[N],v[N],ti; struct qwe { int ne,to; }e[

BZOJ2744: [HEOI2012]朋友圈

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2744 最大团是一个np问题.. 对于本题,做它的逆问题,建反图做最大独立集. 对于A最多取出两个点,枚举一下. 对于B,B是一个二分图. 注意用时间戳加快速度,还有就是注意一下取反的判定(||取反当然是&& #include<cstring> #include<iostream> #include<cstdio> #include<algori

Bzoj 1562: [NOI2009]变换序列 匈牙利算法,二分图匹配

题目: http://cojs.tk/cogs/problem/problem.php?pid=409 409. [NOI2009]变换序列 ★★☆   输入文件:transform.in   输出文件:transform.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 对于N个整数0, 1, ……, N-1,一个变换序列T可以将i变成Ti,其中 定义x和y之间的距离.给定每个i和Ti之间的距离D(i,Ti), 你需要求出一个满足要求的变换序列T.如果有多个满足条

BZOJ 1191 [HNOI2006]超级英雄Hero:二分图匹配 匈牙利算法

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1191 题意: 有m道题,每答对一题才能接着回答下一个问题. 你一道题都不会,但是你有n个"锦囊妙计"(每个只能用一次). 对于每道题,你只能用该题规定的两种锦囊中的一种,来解决这道题. 问你最多能解决多少道题. 题解: 二分图最大匹配. 匈牙利算法. 问题与锦囊匹配. 最大匹配即为最多回答数. 但是题目中要求题目必须连续回答,不能中断. 所以在给每一个问题配对时,一旦匹配不上,

数据结构与算法问题 朋友圈

奈何能力不够,用欧拉回路DFS解题,但是Memory Limit Exceed了,晚上回来再学用并查集. 题目描述: 假如已知有n个人和m对好友关系(存于数字r).如果两个人是直接或间接的好友(好友的好友的好友...),则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈. 假如:n = 5 , m = 3 , r = {{1 , 2} , {2 , 3} , {4 , 5}},表示有5个人,1和2是好友,2和3是好友,4和5是好友,则1.2.3属于一个朋友圈,4.5属于另一个朋