2023“钉耙编程”中国大学生算法设计超级联赛(2)foreverlasting and fried-chicken

2023“钉耙编程”中国大学生算法设计超级联赛(2)foreverlasting and fried-chicken

题目大意

首先引入题目中炸鸡的故事。

https://www.zhihu.com/question/62332494/answer/3076483871

给你一个有 n n n个点 m m m条边的无向图,求这个无向图中出现了多少个 foreverlasting \text{foreverlasting} foreverlasting图。

下面的图像定义了一个 foreverlasting \text{foreverlasting} foreverlasting图。

在这里插入图片描述
当两个 foreverlasting \text{foreverlasting} foreverlasting图的边集之间至少有一条不同的边时,这两个图被认为是不同的。

换句话说,设给定的图为 G ( V , E ) G(V,E) G(V,E),你需要计算满足 V ′ = { v 1 , v 2 , v 3 , v 4 , v 5 , v 6 , v 7 , v 8 } , E ′ = { ( v 1 , v 3 ) , ( v 2 , v 3 ) , ( v 3 , v 4 ) , ( v 3 , v 5 ) , ( v 3 , v 6 ) , ( v 3 , v 7 ) , ( v 4 , v 8 ) , ( v 5 , v 8 ) , ( v 6 , v 8 ) , ( v 7 , v 8 ) } V'=\{v_1,v_2,v_3,v_4,v_5,v_6,v_7,v_8\},E'=\{(v_1,v_3),(v_2,v_3),(v_3,v_4),(v_3,v_5),(v_3,v_6),(v_3,v_7),(v_4,v_8),(v_5,v_8),(v_6,v_8),(v_7,v_8)\} V={v1,v2,v3,v4,v5,v6,v7,v8},E={(v1,v3),(v2,v3),(v3,v4),(v3,v5),(v3,v6),(v3,v7),(v4,v8),(v5,v8),(v6,v8),(v7,v8)}的子图 G ′ ( V ′ , E ′ ) G'(V',E') G(V,E)的数量。

输出答案模 1 0 9 + 7 10^9+7 109+7后的值。

t t t组数据。

1 ≤ t ≤ 10 , 1 ≤ n ≤ 1000 , 0 ≤ m ≤ n ( n − 1 ) 2 1\leq t\leq 10,1\leq n\leq 1000,0\leq m\leq \frac{n(n-1)}{2} 1t10,1n1000,0m2n(n1)

数据保证 ∑ n ≤ 3000 \sum n\leq 3000 n3000


题解

我们可以枚举 foreverlasting \text{foreverlasting} foreverlasting图中 v 3 v_3 v3 v 8 v_8 v8的位置,这两个点分别称为 u u u v v v,设 v t vt vt为同时与 u , v u,v u,v连边的点的个数, c t u ct_u ctu为与 u u u连边的点的个数,那么对于这对 u , v u,v u,v foreverlasting \text{foreverlasting} foreverlasting图的个数为

a n s u , v = C v t 4 × C c t u − 4 2 ans_{u,v}=C_{vt}^4\times C_{ct_u-4}^2 ansu,v=Cvt4×Cctu42

所以答案为

a n s = ∑ u = 1 n ∑ v = 1 n a n s u , v × [ u ≠ v ] ans=\sum\limits_{u=1}^n\sum\limits_{v=1}^nans_{u,v}\times [u\neq v] ans=u=1nv=1nansu,v×[u=v]

注意要特判 u u u v v v连边的情况,如果连边,则将 c t u ct_u ctu减一,计算完 a n s u , v ans_{u,v} ansu,v之后再加回来。

时间复杂度为 O ( n 3 ) O(n^3) O(n3),加上 bitset \text{bitset} bitset优化后,时间复杂度为 O ( n 3 ω ) O(\dfrac{n^3}{\omega}) O(ωn3),可以通过本题。

code

#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
int tq,n,m,ct[1005];
long long vt,now,ans,ny2,ny24;
bitset<1005>wt,z[1005];
long long mi(long long t,long long v){
	if(!v) return 1;
	long long re=mi(t,v/2);
	re=re*re%mod;
	if(v&1) re=re*t%mod;
	return re;
}
int rd(){
	int re=0;
	char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9'){
		re=re*10+ch-'0';
		ch=getchar();
	}
	return re;
}
int main()
{
	tq=rd();
	ny2=mi(2,mod-2);
	ny24=mi(24,mod-2);
	while(tq--){
		n=rd();m=rd();
		for(int i=1,x,y;i<=m;i++){
			x=rd();y=rd();
			z[x][y]=z[y][x]=1;
			++ct[x];++ct[y];
		}
		ans=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i==j) continue;
				wt=z[i]&z[j];
				vt=wt.count();
				ct[i]-=z[i][j];
				if(vt>=4&&ct[i]>=6){
					now=vt*(vt-1)%mod*(vt-2)%mod*(vt-3)%mod*ny24%mod;
					now=now*(ct[i]-4)%mod*(ct[i]-5)%mod*ny2%mod;
					ans=(ans+now)%mod;
				}
				ct[i]+=z[i][j];
			}
		}
		printf("%lld\n",ans);
		for(int i=1;i<=n;i++){
			ct[i]=0;
			z[i].reset();
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值