foreverlasting and fried-chicken hdu7293

Problem - 7293

题目大意:给出一个n个点,m条边的图,问其中包含了几个下面这样的子图

foreverlasting and fried-chicken hdu7293_第1张图片

1<=n<=1000;

思路:我们要找两个点u,v,他们至少有4个公共点,且至少有一个点的度数至少为6,其中还要判断两个点之间有没有直连的边,如果有,这个边不能放在度数的统计中,所以我们建立邻接矩阵存图,便于查找这样的边,同时用bitset将每个点连接的点记录下来,那么两个点的公共点的数量就等于两个bitset求&之后1的数量,然后再判断满足以上要求的点的度数,如果不算直连边也>=6,那么答案就加上C(它的度数,4)*C(另一个点度数,2)

#include
//#include<__msvc_all_public_headers.hpp>
using namespace std;
typedef long long ll;
const int N = 1010;
int a[N][N];
ll cnt[N];
const ll mod = 1e9 + 7;
bitset b[N];
void init(int n)
{//初始化矩阵、bitset
	for (int i = 1; i <= n; i++)
	{
		b[i].reset();
		cnt[i] = 0;
		for (int j = 1; j <= n; j++)
		{
			a[i][j] = 0;
		}
	}
}
ll getnum(ll x, ll y)
{//计算两个点提供的总贡献
	return (((x) * (x - 1) * (x - 2) * (x - 3) / 24) % mod * (y) * (y - 1) / 2) % mod;
}
int main()
{
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		init(n);
		ll ans = 0;
		for (int i = 1; i <= m; i++)
		{
			int u, v;
			cin >> u >> v;
			a[u][v] = 1;
			a[v][u] = 1;//邻接矩阵存图
		}
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				b[i].set(j, a[i][j]);//将矩阵的每一行存入bitset
			}
		}
		for (int i = 1; i <= n; i++)
		{
			for (int j = i + 1; j <= n; j++)
			{
				ll c = (b[i] & b[j]).count();//求公共点子节点的数量
				if (c <= 3) continue;//至少要等于4
				ll temp = b[i].count();
				ll temp2 = b[j].count();//两个点的度数
				if (a[i][j] == 1) temp -= 1, temp2 -= 1;//有直连边,度数都要-1
				temp -= 4;
				temp2 -= 4;//有几个可以作为目标图最上边那两个点的 				
				if (temp > 0)
				{
					ans = (ans + getnum(c, temp)) % mod;
				}
				if (temp2 > 0)
				{//对两个点分别计算
					ans = (ans + getnum(c, temp2)) % mod;
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}

 

你可能感兴趣的:(图论,位运算,算法,c++)