【HDU 5917】Instability

1.题目链接。题目大意:给定一个无向图,求这个图有多少个点的集合,每个集合至少包含一个关于这个图的独立集或者团。并且集合的元素个数要大于等于3.

2。其实这个题目就是拉姆齐定理的应用,根据拉姆齐定理,6个人中一定有三个人互相认识或者互相不认识。这个认识和不认识就是我们这道题目中的边,然后更具这个题目我们可以算出来大于等于六个人一定满足的,总共的选择方案是(C(n,0)+C(n,1)....C(n,n)=pow(2,n),减去0到5.然后我们知道,小于三一定是没戏的,那么只有3,4,5了。这个时候我们直接暴力验证就行了。实际上也是比较容易的一个题目,只需要记得拉姆齐定理即可。

#include<bits/stdc++.h>
using namespace std;
#pragma warning(disable:4996)
const int N = 55;
const int mod = 1e9 + 7;
bool vis[N][N];
int n, m;
#pragma warning(disable:4996)
long long ans, c[N][N];
#define ll long long
void init() {
	c[1][1] = c[0][1] = 1;
	for (int i = 2; i <= n; i++)
		for (int j = 0; j <= i; j++) {
			if (j == 0) c[j][i] = 1;
			else c[j][i] = (c[j][i - 1] + c[j - 1][i - 1]) % mod;
		}
}
ll qpow(ll a, ll b)
{
	ll res = 1;
	while (b)
	{
		if (b & 1)
			res = res * a%mod;
		a = a * a%mod;
		b >>= 1;
	}
	return res;
}
bool judge(int a, int b, int c) {
	if (vis[a][b] && vis[a][c] && vis[b][c]) return true;
	if (!vis[a][b] && !vis[a][c] && !vis[b][c]) return true;
	return false;
}

bool judge(int a, int b, int c, int d) {
	if (judge(a, b, c)) return true;
	if (judge(a, b, d)) return true;
	if (judge(a, c, d)) return true;
	if (judge(b, c, d)) return true;
	return false;
}

bool judge(int a, int b, int c, int d, int e) {
	if (judge(a, b, c, d)) return true;
	if (judge(a, b, c, e)) return true;
	if (judge(a, c, d, e)) return true;
	if (judge(b, c, d, e)) return true;
	if (judge(a, b, d, e)) return true;
	return false;
}
int main() {
	int T;
	scanf("%d", &T);
	for (int I = 1; I <= T; I++) {
		memset(vis, false, sizeof(vis));
		scanf("%d%d", &n, &m);
		for (int i = 0; i < m; i++) {
			int ta, tb;
			scanf("%d%d", &ta, &tb);
			vis[ta][tb] = true;
			vis[tb][ta] = true;
		}
		ans = 0;
		if (n >= 6) {
			init();
			ans += qpow(2, n);
			for (int i = 0; i < 6; i++) {
				ans -= c[i][n];
				ans += mod;
				ans %= mod;
			}
		}
		for (int i = 1; i <= n; i++)
			for (int j = i + 1; j <= n; j++)
				for (int k = j + 1; k <= n; k++)
					if (judge(i, j, k))
						ans++;
		for (int i = 1; i <= n; i++)
			for (int j = i + 1; j <= n; j++)
				for (int k = j + 1; k <= n; k++)
					for (int l = k + 1; l <= n; l++)
						if (judge(i, j, k, l))
							ans++;
		for (int i = 1; i <= n; i++)
			for (int j = i + 1; j <= n; j++)
				for (int k = j + 1; k <= n; k++)
					for (int u = k + 1; u <= n; u++)
						for (int v = u + 1; v <= n; v++)
							if (judge(i, j, k, u, v))
								ans++;
		ans %= mod;
		printf("Case #%d: %lld\n", I, ans);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值