首先将朋友通过并查集缩起来,因为$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; }