Problem - 7293
题目大意:给出一个n个点,m条边的图,问其中包含了几个下面这样的子图
1<=n<=1000;
思路:我们要找两个点u,v,他们至少有4个公共点,且至少有一个点的度数至少为6,其中还要判断两个点之间有没有直连的边,如果有,这个边不能放在度数的统计中,所以我们建立邻接矩阵存图,便于查找这样的边,同时用bitset将每个点连接的点记录下来,那么两个点的公共点的数量就等于两个bitset求&之后1的数量,然后再判断满足以上要求的点的度数,如果不算直连边也>=6,那么答案就加上C(它的度数,4)*C(另一个点度数,2)
#include<bits/stdc++.h>
//#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<N> 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;
}