zoukankan      html  css  js  c++  java
  • BZOJ3548 : [ONTAK2010]Party

    首先将朋友通过并查集缩起来,因为$Pgeqfrac{n(n-1)}{3}$,所以最后最多剩下$46$个点。

    将自相矛盾的点删掉,就变成求最大权独立集问题,这等于求补图的最大团。

    然后直接用Bron-Kerbosch算法枚举所有极大团,枚举的时候更新答案即可。

    时间复杂度$O(3^frac{n}{3})$。

    #include<cstdio>
    #define N 46
    typedef unsigned long long ll;
    int n,m,q,i,j,x,y,ans,sum,flag,size[N];ll G[N];
    int f[255],v[255],cnt,val[N],g[N][N];char tab[65536];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
    inline int ctz(ll s){
      if(!s)return 64;
      if(s&65535)return tab[s&65535];
      s>>=16;
      if(s&65535)return tab[s&65535]+16;
      return tab[s>>16]+32;
    }
    void BronKerbosch(ll allow,ll forbid,int s){
      if(!allow&&!forbid){
        if(s>ans)ans=s,sum=1;else if(s==ans)sum++;
        return;
      }
      if(!allow)return;
      int pivot=ctz(allow|forbid);
      ll z=allow&~G[pivot];
      for(int u=ctz(z);u<n;u+=ctz(z>>(u+1))+1){
        BronKerbosch(allow&G[u],forbid&G[u],s+size[u]);
        allow^=1ULL<<u;forbid|=1ULL<<u;
      }
    }
    void BronKerbosch2(ll allow,ll forbid,int s){
      if(!allow&&!forbid){
        if(s>ans)ans=s,sum=1;else if(s==ans)sum++;
        return;
      }
      if(!allow)return;
      int pivot=ctz(allow|forbid);
      ll z=allow&~G[pivot];s++;
      for(int u=ctz(z);u<n;u+=ctz(z>>(u+1))+1){
        BronKerbosch2(allow&G[u],forbid&G[u],s);
        allow^=1ULL<<u;forbid|=1ULL<<u;
      }
    }
    int main(){
      for(i=0;i<65536;i++)tab[i]=__builtin_ctz(i);
      read(n),read(m),read(q);
      for(i=1;i<=n;i++)f[i]=i;
      while(m--){
        read(x),read(y);
        if(F(x)!=F(y))f[f[x]]=f[y];
      }
      for(i=1;i<=n;i++)v[i]=-1;
      for(i=1;i<=n;i++){
        if(v[F(i)]<0)v[f[i]]=cnt++;
        val[v[f[i]]]++;
      }
      while(q--){
        read(x),read(y);
        x=v[f[x]],y=v[f[y]];
        if(x==y)val[x]=0;else g[x][y]=g[y][x]=1;
      }
      for(n=cnt,cnt=i=0;i<n;i++)if(val[i])v[i]=cnt,f[cnt++]=i;
      if(!cnt)return puts("0 1"),0;
      for(i=0;i<n;i++)if(val[i])size[v[i]]=val[i];
      for(n=cnt,i=0;i<n;i++)if(size[i]>1)flag=1;
      for(i=0;i<n;i++)G[i]=(1ULL<<n)-1-(1ULL<<i);
      for(i=0;i<n;i++)for(j=0;j<n;j++)if(g[f[i]][f[j]])G[i]^=1ULL<<j;
      flag?BronKerbosch((1ULL<<n)-1,0,0):BronKerbosch2((1ULL<<n)-1,0,0);
      return printf("%d %d",ans,sum),0;
    }
    

      

  • 相关阅读:
    Flink中的window、watermark和ProcessFunction(三)
    ThreadLocal刨根问底
    Flink的流处理API(二)
    Flink简介(一)
    SparkStreaming
    SparkSQL
    Spark入门
    SparkCore
    【HNOI2009】 最小圈
    【BOI 2002】 双调路径
  • 原文地址:https://www.cnblogs.com/clrs97/p/5667766.html
Copyright © 2011-2022 走看看