题意:给出一个n个点的图(最多50),定义合法的顶点集合为:至少存在一个子集(size>=3)且这个子集是一个团或者独立集。求合法集合的个数。
题解:现场赛怕是群脸懵逼吧。。。有一个Ramsey定理,说的是,世界上任选6个人,必然存在至少三个人相互认识或者相互不认识。也就是说给一个大于等于6个点的图,他的最大团或者最大独立集必然大于等于3
那么问题很显然了,6以及6以上的直接统计345的暴力统计就行了 就是说ans=3的个数+4的个数+5的个数+C(n,6)+C(n,7)+…………+C(n,n)=2^n-C(n,0)-C(n,1)-C(n,2)-3不合法的个数-4不合法的个数-5不合法的个数。
AC了之后整个人都神经了不少啊。。。
Code:
#include<bits/stdc++.h>
#define REP(i,x,y) for (int i=x;i<=y;i++)
using namespace std;
const int maxn = 55;
const int MOD = 1e9+7;
int T;
int mp[maxn][maxn];
int Cas=1;
int m,n;
void init(){
memset(mp,0,sizeof mp);
}
void input(){
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
mp[u][v]=mp[v][u]=1;
}
}
bool check(int x,int y,int z){
int t = mp[x][y]+mp[x][z]+mp[y][z];
if (t==0||t==3)return true;
return false;
}
bool check(int x,int y,int z,int w){
return (check(x,y,z)||check(x,y,w)||check(x,z,w)||check(y,z,w));
}
bool check(int a,int b,int c,int d,int e){
return (check(a,b,c)||check(a,b,d)||check(a,b,e)||check(a,c,d)||check(a,c,e)||check(a,d,e)||check(b,c,d)||check(b,c,e)||check(b,d,e)||check(c,d,e));
}
void solve(){
long long ans = 1;
for (int i=1;i<=n;i++){
ans = ans*2;
ans%=MOD;
}
ans-= n;
ans--;
ans-=n*(n-1)/2;
ans+=MOD;
ans%=MOD;
REP(i,1,n)REP(j,i+1,n)REP(k,j+1,n) if (!check(i,j,k))ans--;
REP(i,1,n)REP(j,i+1,n)REP(k,j+1,n)REP(l,k+1,n)if (!check(i,j,k,l)) ans--;
REP(i,1,n)REP(j,i+1,n)REP(k,j+1,n)REP(l,k+1,n)REP(p,l+1,n)if (!check(i,j,k,l,p)) ans--;
ans+=MOD;
ans%=MOD;
printf("Case #%d: %lld\n",Cas++,ans);
}
int main(){
scanf("%d",&T);
while (T--){
init();
input();
solve();
}
return 0;
}