思路
题目大致意思是给定一个无向图(点数>=3),求这个集合有多少子集满足这个子集中存在K3完全图或者三个互相孤立的点
这里要用到Ramsey定理进行优化 具体可以参见 Ramsey定理简介
定理中红色的Km或者蓝色的Kn在本题中就可以看成完全图或者互相孤立的点
于是对于n>=6的集合,C(n,6)即为数量,因为r(3,3)=6 ( r(m,n)意义参见上面Ramsey链接 )。
对于点的数量是3,4,5的子集,枚举即可
代码示例
#include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn=55; const int mod=1000000007; typedef long long ll; ll c[maxn][maxn]; int mat[maxn][maxn]; void init() { c[0][0]=1; c[1][0]=c[1][1]=1; for(int i=2;i<maxn;++i){ for(int j=0;j<=i;++j){ if(j==0||j==i) c[i][j]=1; else c[i][j]=c[i-1][j-1]+c[i-1][j]; } } } int fun(int n) { ll ans=0; for(int i=6;i<=n;++i){ ans+=c[n][i]; } ans%=mod; return ans; } bool check(int i,int j,int k) { ll ans=0; int tmp[3]; tmp[0]=i; tmp[1]=j; tmp[2]=k; int sum=0; for(int p=0;p<=2;++p){ for(int q=0;q<p;++q){ sum+=mat[tmp[p]][tmp[q]]; } } if(sum==0||sum==3) return 1; else return 0; } int check3(int n) { ll ans=0; for(int i=1;i<=n;++i){ for(int j=1;j<i;++j){ for(int k=1;k<j;++k){ if(check(i,j,k)) ans++; } } } return ans; } int check4(int n) { ll ans=0; for(int i=1;i<=n;++i){ for(int j=1;j<i;++j){ for(int k=1;k<j;++k){ for(int l=1;l<k;++l){ if(check(i,j,k)||check(i,j,l)||check(i,k,l)||check(j,k,l)) ans++; } } } } return ans; } int check5(int n) { ll ans=0; for(int i=1;i<=n;++i){ for(int j=1;j<i;++j){ for(int k=1;k<j;++k){ for(int l=1;l<k;++l){ for(int m=1;m<l;++m) if(check(i,j,k)||check(i,j,l)||check(i,k,l)||check(j,k,l)||check(i,j,m)|| check(i,k,m)||check(i,l,m)||check(j,k,m)||check(j,l,m)||check(k,l,m)) ans++; } } } } return ans; } int main() { //freopen("read.txt","r",stdin); ios::sync_with_stdio(false); init(); int t,n,m; int Case=0; cin>>t; ll ans; while(t--) { //cout<<c[50][25]<<endl; clr(mat,0); cin>>n>>m; for(int i=0;i<m;++i){ int x,y; cin>>x>>y; mat[x][y]=1; mat[y][x]=1; } ans=0; if(n>=6){ ans+=fun(n); ans+=check3(n); ans+=check4(n); ans+=check5(n); } if(n==5){ ans+=check3(n); ans+=check4(n); ans+=check5(n); } if(n==4){ ans+=check3(n); //cout<<ans<<endl; ans+=check4(n); //cout<<ans<<endl; } if(n==3) ans+=check3(n); cout<<"Case #"<<++Case<<": "<<ans%mod<<endl; } return 0; }