题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=3812
题解
考虑求非强连通子图的数量,假设为,那么答案就是。现在考虑求。
假设表示用这些点能构成的强连通图的个数,表示用这些点能构成的非强连通图的方案数,其中构成个强连通分量则对的贡献为。容易发现
那么
容易发现,此时需要的是不包含的,因此在求出之前是不能的。
代码
#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;
}