毒 瘤 计 数!
XSY 题意不是很清楚,这里给出更加清楚的:
给定一张 n n n 个点 m m m 条边的无向图,保证该图整个图为一个强联通分量,且无重边自环。现在需要求出:有多少种删边方案,使得删完边后,整个图依旧是一个强联通分量。数据范围: n ≤ 15 , m ≤ n ( n − 1 ) n\leq 15,m\leq n(n-1) n≤15,m≤n(n−1)。
记 E [ U , V ] E[U,V] E[U,V] 表示题目给的所有边中,起点在 U U U 中、终点在 V V V 中的所有边的集合,其中 U , V U,V U,V 为点集。
对于一个点集 S S S,设其任意形成的某一张图为 G G G(“形成”是指通过题目给的边形成),我们对其连边后缩点,最后得到的肯定是若干个强连通分量(称为 scc)之间有连边,形成一个 DAG。而题目要求的是只有一个 scc,那么我们就要用 S S S 能形成的图的总数量 2 E [ S , S ] 2^{E[S,S]} 2E[S,S] 减去 S S S 形成的图是多个 scc 的 DAG 的情况。
那么我们枚举这个 DAG 中,出度为 0 0 0 的那些 scc 所包含的点的集合 T T T,然后再考虑在确定了 T T T 的基础上再确定 G G G 的数量。
首先 S − T S-T S−T(中间是减号)的点之间可以乱连, S − T S-T S−T 的点向 T T T 的点也可以乱连,这部分的方案是 2 E [ S − T , S − T ] × 2 E [ S − T , T ] 2^{E[S-T,S-T]}\times 2^{E[S-T,T]} 2E[S−T,S−T]×2E[S−T,T]。
于是我们可以暂时建立一个等量关系:
2
E
[
S
,
S
]
=
∑
T
⊆
S
,
T
≠
∅
g
T
×
2
E
[
S
−
T
,
S
−
T
]
×
2
E
[
S
−
T
,
T
]
2^{E[S,S]}=\sum_{T\subseteq S,T\neq \emptyset}g_T\times 2^{E[S-T,S-T]}\times 2^{E[S-T,T]}
2E[S,S]=T⊆S,T=∅∑gT×2E[S−T,S−T]×2E[S−T,T]
其中
g
T
g_T
gT 可以暂时理解为点集
T
T
T 形成的图为若干个强联通分量的方案数,但显然这样定义是不对的,原因下面会说。
设 f X f_X fX 表示点集 X X X 形成的图为一个强联通分量的方案数。(那么 f f f 就是题目所求)
那么就可以直接 g T = ∑ s 1 , s 2 , ⋯ , s k ∏ i = 1 k f s i g_T=\sum\limits_{s_1,s_2,\cdots,s_k}\prod\limits_{i=1}^k f_{s_i} gT=s1,s2,⋯,sk∑i=1∏kfsi 了吗?(其中 ∑ s 1 , s 2 , ⋯ , s k \sum\limits_{s_1,s_2,\cdots,s_k} s1,s2,⋯,sk∑ 的意思是将 T T T 划分为若干个scc s 1 , s 2 , ⋯ , s k s_1,s_2,\cdots,s_k s1,s2,⋯,sk,即枚举 s 1 ∪ s 2 ∪ ⋯ ∪ s k = T s_1\cup s_2\cup\cdots\cup s_k=T s1∪s2∪⋯∪sk=T 满足 ∀ i ≠ j , s i ∩ s j = ∅ \forall i\neq j,s_i\cap s_j=\emptyset ∀i=j,si∩sj=∅)
当然不行,因为 E [ S − T , S − T ] E[S-T,S-T] E[S−T,S−T] 里面的是随便连的,有可能会形成其他的出度为 0 0 0 的 scc,这与我们的假设不符,会导致算重。这也就是 g T g_T gT 不能直接定义为“点集 T T T 形成的图为若干个强联通分量的方案数”的原因。
因此我们需要容斥。于是设容斥系数
c
o
e
f
k
coef_k
coefk:
g
T
=
∑
s
1
,
s
2
,
⋯
,
s
k
c
o
e
f
k
∏
i
=
1
k
f
s
i
g_T=\sum\limits_{s_1,s_2,\cdots,s_k}coef_k\prod\limits_{i=1}^k f_{s_i}
gT=s1,s2,⋯,sk∑coefki=1∏kfsi
对于
T
T
T 的某一种划分方案
s
1
,
s
2
,
⋯
,
s
k
s_1,s_2,\cdots,s_k
s1,s2,⋯,sk,我们在
s
1
,
s
2
,
⋯
,
s
k
s_1,s_2,\cdots,s_k
s1,s2,⋯,sk 中任意选出若干个并起来得到
T
′
T'
T′,那么当我们在枚举
T
=
T
′
T=T'
T=T′ 时,这种方案都被算了一次,于是这种方案实际上被算了:
∑
i
=
0
k
(
k
i
)
c
o
e
f
i
\sum_{i=0}^k\binom{k}{i}coef_i
i=0∑k(ik)coefi
理论上,这种方案应该只能被算一次,于是:
1
=
∑
i
=
1
k
(
k
i
)
c
o
e
f
i
1=\sum_{i=1}^k\binom{k}{i}coef_i
1=i=1∑k(ik)coefi
根据二项式反演:
c
o
e
f
k
=
∑
i
=
1
k
(
−
1
)
k
−
i
(
k
i
)
=
(
∑
i
=
0
k
(
k
i
)
1
i
(
−
1
)
k
−
i
)
−
(
−
1
)
k
=
(
1
−
1
)
k
−
(
−
1
)
k
=
(
−
1
)
k
+
1
\begin{aligned} coef_k&=\sum_{i=1}^k(-1)^{k-i}\binom{k}{i}\\ &=\left(\sum_{i=0}^k\binom{k}{i}1^i(-1)^{k-i}\right)-(-1)^k\\ &=(1-1)^k-(-1)^k\\ &=(-1)^{k+1} \end{aligned}
coefk=i=1∑k(−1)k−i(ik)=(i=0∑k(ik)1i(−1)k−i)−(−1)k=(1−1)k−(−1)k=(−1)k+1
于是:
g
T
=
∑
s
1
,
s
2
,
⋯
,
s
k
(
−
1
)
k
+
1
∏
i
=
1
k
f
s
i
g_T=\sum\limits_{s_1,s_2,\cdots,s_k}(-1)^{k+1}\prod\limits_{i=1}^k f_{s_i}
gT=s1,s2,⋯,sk∑(−1)k+1i=1∏kfsi
如果求出了
g
g
g,那么就能跟
f
f
f 扯上点关系。
根据我们刚开始那条式子可以对
g
g
g 进行递推:
2
E
[
S
,
S
]
=
∑
T
⊆
S
,
T
≠
∅
g
T
×
2
E
[
S
−
T
,
S
−
T
]
×
2
E
[
S
−
T
,
T
]
g
S
=
2
E
[
S
,
S
]
−
∑
T
⫋
S
,
T
≠
∅
g
T
×
2
E
[
S
−
T
,
S
−
T
]
×
2
E
[
S
−
T
,
T
]
\begin{aligned} 2^{E[S,S]}&=\sum_{T\subseteq S,T\neq \emptyset}g_T\times 2^{E[S-T,S-T]}\times 2^{E[S-T,T]}\\\\ g_S&=2^{E[S,S]}-\sum_{T\subsetneqq S,T\neq \emptyset}g_T\times 2^{E[S-T,S-T]}\times 2^{E[S-T,T]} \end{aligned}
2E[S,S]gS=T⊆S,T=∅∑gT×2E[S−T,S−T]×2E[S−T,T]=2E[S,S]−T⫋S,T=∅∑gT×2E[S−T,S−T]×2E[S−T,T]
于是
g
g
g 求出来了。
观察刚刚推出来的
g
g
g 与
f
f
f 的式子:
g
T
=
∑
s
1
,
s
2
,
⋯
,
s
k
(
−
1
)
k
+
1
∏
i
=
1
k
f
s
i
g_T=\sum\limits_{s_1,s_2,\cdots,s_k}(-1)^{k+1}\prod\limits_{i=1}^k f_{s_i}
gT=s1,s2,⋯,sk∑(−1)k+1i=1∏kfsi
那么:
g
T
=
(
−
1
)
×
∑
s
1
⊆
T
,
s
1
≠
∅
f
s
1
g
T
−
s
1
\begin{aligned} g_T=(-1)\times \sum_{s_1\subseteq T,s_1\neq \emptyset}f_{s_1}g_{T-s_1}\\ \end{aligned}
gT=(−1)×s1⊆T,s1=∅∑fs1gT−s1
(其中
s
1
s_1
s1 枚举的是
T
T
T 中编号最小的点所在的scc)
也由此可知应该令 g ∅ = − 1 g_{\emptyset}=-1 g∅=−1。
于是:
g
T
=
f
T
+
(
−
1
)
×
∑
s
1
⫋
T
,
s
1
≠
∅
f
s
1
g
T
−
s
1
f
T
=
g
T
+
∑
s
1
⫋
T
,
s
1
≠
∅
f
s
1
g
T
−
s
1
\begin{aligned} g_T=f_T+(-1)\times\sum_{s_1\subsetneqq T,s_1\neq \emptyset}f_{s_1}g_{T-s_1}\\ f_T=g_T+\sum_{s_1\subsetneqq T,s_1\neq \emptyset}f_{s_1}g_{T-s_1} \end{aligned}
gT=fT+(−1)×s1⫋T,s1=∅∑fs1gT−s1fT=gT+s1⫋T,s1=∅∑fs1gT−s1
于是就能求出
f
S
f_S
fS 了。
这道题的总体思路是先求 S S S 形成的图是若干个出度为 0 0 0 的 scc 的方案数 g S g_S gS(用总的方案数减去 DAG 的方案数),再求 S S S 形成的图是一个出度为 0 0 0 的 scc 的方案数 f S f_S fS(用 g S g_S gS 减去多个 scc 的方案数)。
#include<bits/stdc++.h>
#define N 17
#define PN 33000
using namespace std;
namespace modular
{
const int mod=1000000007;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;
inline int poww(int a,int b)
{
int ans=1;
while(b)
{
if(b&1) ans=mul(ans,a);
a=mul(a,a);
b>>=1;
}
return ans;
}
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^'0');
ch=getchar();
}
return x*f;
}
int n,m,maxn,E1[PN],E2[PN][N];
int pow2[N*N],minid[PN];
int f[PN],g[PN];
void init()
{
pow2[0]=1;
for(int i=1;i<=m;i++)
pow2[i]=add(pow2[i-1],pow2[i-1]);
maxn=pow2[n]-1;
for(int i=1;i<=maxn;i++)
{
if(i&1) minid[i]=1;
else minid[i]=minid[i>>1]+1;
}
}
int main()
{
n=read(),m=read();
if(m<n)
{
puts("0");
return 0;
}
init();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
int pu=pow2[u-1],pv=pow2[v-1];
for(int S=maxn^pu^pv,now=S;;now=(now-1)&S)
{
E1[now^pu^pv]++;
if(!now) break;
}
for(int S=maxn^pu,now=S;;now=(now-1)&S)
{
if((now>>(v-1))&1) continue;
E2[now^pu][v]++;
if(!now) break;
}
}
g[0]=mod-1;
for(int S=1;S<=maxn;S++)
{
g[S]=pow2[E1[S]];
for(int T=(S-1)&S;T!=0;T=(T-1)&S)
{
int sum=0,now=T;
while(now)
{
sum+=E2[S^T][minid[now]];
now^=pow2[minid[now]-1];
}
g[S]=dec(g[S],mul(g[T],mul(pow2[E1[S^T]],pow2[sum])));
}
}
for(int T=1;T<=maxn;T++)
{
f[T]=g[T];
int p=pow2[minid[T]-1],S=T^p;
if(!S) continue;
for(int s1=(S-1)&S;;s1=(s1-1)&S)
{
f[T]=add(f[T],mul(f[s1^p],g[T^(s1^p)]));
if(!s1) break;
}
}
printf("%d\n",f[maxn]);
return 0;
}