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;
}

  

原文地址:https://www.cnblogs.com/clrs97/p/5667766.html