题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=3812
题解
考虑求非强连通子图的数量,假设为 g g g,那么答案就是 2 m − g 2^m-g 2m−g。现在考虑求 g g g。
假设
f
s
f_s
fs表示用
s
s
s这些点能构成的强连通图的个数,
g
s
g_s
gs表示用
s
s
s这些点能构成的非强连通图的方案数,其中构成
i
i
i个强连通分量则对
g
s
g_s
gs的贡献为
(
−
1
)
i
(-1)^i
(−1)i。容易发现
g
s
=
f
s
−
∑
t
⊂
s
,
u
∈
t
g
t
f
s
−
t
g_s=f_s-\sum_{t\subset s,u\in t} g_tf_{s-t}
gs=fs−t⊂s,u∈t∑gtfs−t
那么
f
s
=
2
e
s
−
∑
t
⊆
s
,
t
̸
=
∅
2
e
s
−
t
+
e
s
−
t
,
t
g
s
f_s=2^{e_s}-\sum_{t\subseteq s,t\not= \varnothing}2^{e_{s-t}+e_{s-t,t}}g_s
fs=2es−t⊆s,t̸=∅∑2es−t+es−t,tgs
容易发现,
f
s
f_s
fs此时需要的是不包含
f
s
f_s
fs的
g
s
g_s
gs,因此
g
s
g_s
gs在求出
f
s
f_s
fs之前是不能
+
f
s
+f_s
+fs的。
代码
#include <cstdio>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=15;
const int maxm=1<<maxn;
const int mod=1000000007;
int n,m,f[maxm+10],g[maxm+10],pow[maxn*maxn+10],ecnt[maxm+10][maxn+2],in[maxm+10];
inline int lowbit(int x)
{
return x&(-x);
}
int main()
{
n=read();
m=read();
int full=(1<<n)-1;
for(int i=1; i<=m; ++i)
{
int a=read(),b=read();
for(int j=1; j<=full; ++j)
{
if((1<<(a-1))&j)
{
++ecnt[j][b];
}
}
}
pow[0]=1;
for(int i=1; i<=m; ++i)
{
pow[i]=pow[i-1]<<1;
if(pow[i]>=mod)
{
pow[i]-=mod;
}
}
f[0]=g[0]=1;
for(int s=1; s<=full; ++s)
{
int sk=s^lowbit(s);
for(int t=sk; t; t=sk&(t-1))
{
g[s]-=1ll*f[s^t]*g[t]%mod;
if(g[s]<0)
{
g[s]+=mod;
}
}
for(int i=1; i<=n; ++i)
{
if((1<<(i-1))&s)
{
in[s]+=ecnt[s][i];
}
}
f[s]+=pow[in[s]];
for(int t=s; t; t=s&(t-1))
{
int e=0;
for(int i=1; i<=n; ++i)
{
if((1<<(i-1))&t)
{
e+=ecnt[s^t][i];
}
}
f[s]-=1ll*pow[e+in[s^t]]*g[t]%mod;
if(f[s]<0)
{
f[s]+=mod;
}
}
g[s]+=f[s];
if(g[s]>=mod)
{
g[s]-=mod;
}
}
printf("%d\n",f[full]);
return 0;
}