zoukankan      html  css  js  c++  java
  • BZOJ5335 : [TJOI2018]智力竞赛

    二分答案,转化成求最少的路径,覆盖住所有权值$leq mid$的点。

    建立二分图,若$i$的后继为$j$,则连边$i ightarrow j$,求出最大匹配,则点数减去最大匹配数即为最少需要的路径数量。

    特别地如果某个点$i$的权值$>mid$,则它可以不经过,连边$i ightarrow i$表示忽略该点。

    因为这是稠密图,用bitset优化匈牙利算法即可。

    时间复杂度$O(frac{m^3log m}{32})$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef unsigned int U;
    const int N=505,M=N/32+1;
    int n,m,tot,k,i,j,x,l,r,mid,ans,v[N],q[N],f[N],cnt;U a[N][M],g[N][M],b[M];
    inline void set1(U v[],int x){v[x>>5]|=1U<<(x&31);}
    inline void flip(U v[],int x){v[x>>5]^=1U<<(x&31);}
    bool find(int x){
      for(int i=0;i<=tot;i++)while(1){
        U o=g[x][i]&b[i];
        if(!o)break;
        int y=i<<5|__builtin_ctz(o);
        flip(b,y);
        if(!f[y]||find(f[y]))return f[y]=x,1;
      }
      return 0;
    }
    bool check(int lim){
      for(i=1;i<=m;i++)for(j=0;j<=tot;j++)g[i][j]=a[i][j];
      for(i=1;i<=m;i++)if(v[i]>lim)set1(g[i],i);
      for(i=1;i<=m;i++)f[i]=0;
      cnt=0;
      for(i=1;i<=m;i++){
        for(j=1;j<=m;j++)set1(b,j);
        if(find(i))cnt++;
      }
      return m-cnt<=n;
    }
    int main(){
      scanf("%d%d",&n,&m);n++;tot=m>>5;
      for(i=1;i<=m;i++){
        scanf("%d%d",&v[i],&k);
        q[i]=v[i];
        while(k--)scanf("%d",&x),set1(a[i],x);
      }
      sort(q+1,q+m+1);
      l=1,r=m;
      while(l<=r){
        mid=(l+r)>>1;
        if(check(q[mid]))l=(ans=mid)+1;else r=mid-1;
      }
      if(ans==m)puts("AK");else printf("%d",q[ans+1]);
    }
    

      

  • 相关阅读:
    第一次结对编程作业
    第一次个人编程作业
    软工实践作业(一)
    通往SDN之路:可编程网络的思想史
    week9:Security: Web Security
    week8:Security: Encrypting and Signing
    week7:Technology: Application Protocols
    week6:Technology: Transport Control Protocol (TCP)
    10.消除左递归
    9.DFA最小化,语法分析初步
  • 原文地址:https://www.cnblogs.com/clrs97/p/9536191.html
Copyright © 2011-2022 走看看