HDU 5917:Ramsey定理

题意:给出一个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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值