zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    //    }
      return 0;
    }
  • 相关阅读:
    三个录屏软件
    不用 PS 和 AI,5个网站能做出更好看的设计
    使用vue.js开发小程序
    js异步处理
    HTTP、HTTP1.0、HTTP1.1、HTTP2.0、HTTPS
    Chrome不支持css字体小于12px的解决办法
    处理CSS前缀问题的神器——AutoPrefixer
    CSS | 字体系列
    qemu-img 命令讲解
    全面理解 git
  • 原文地址:https://www.cnblogs.com/Narh/p/9280714.html
Copyright © 2011-2022 走看看