令
fS
表示点集
S
的答案,
那么
fS=gS−∑T∈SgT×MT,S−T
,
MS,T
表示把点集
S
分成几个联通块后连到
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int P=1e9+7,N=1<<12;
int t,n,m;
int e[15][15],f[N],size[N],edge[N],g[N],ug[N],h[N],mer[1<<10|5][1<<10|5],pw[1010];
int G(int S){
if(~g[S]) return g[S];
int ret=pw[edge[S]],lst=S&-S; S^=lst;
for(int s=S;s;s=(s-1)&S)
ret=(ret-1LL*G(S^s^lst)*pw[edge[s]])%P;
return g[S^lst]=ret;
}
int Edge(int S,int T){
return edge[S^T]-edge[S]-edge[T];
}
int M(int S,int T){
if(!Edge(S,T)) return 0;
if(~mer[S][T]) return mer[S][T];
int ret=1LL*G(S)*Edge(S,T)%P,lst=S&-S; S^=lst;
for(int s=S;s;s=(s-1)&S){
ret=(ret+1LL*M(s,T)*G(S^s^lst)%P*Edge(S^s^lst,T))%P;
}
return mer[S^lst][T]=ret;
}
int F(int S){
if(~f[S]) return f[S];
int ret=G(S),lst=S&-S; S^=lst;
for(int s=S;s;s=(s-1)&S)
ret=(ret-1LL*F(S^s^lst)*M(s,S^s^lst))%P;
return f[S^lst]=ret;
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
scanf("%d",&t);
for(int i=1;i<(1<<10);i++) size[i]=size[i>>1]+(i&1);
pw[0]=1; for(int i=1;i<=100;i++) pw[i]=2LL*pw[i-1]%P;
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) e[i][j]=1;
for(int i=1,x,y;i<=m;i++)
scanf("%d%d",&x,&y),e[x][y]=e[y][x]=0;
memset(mer,-1,sizeof(mer));
for(int i=0;i<(1<<n);i++)
f[i]=g[i]=ug[i]=h[i]=-1;
for(int S=1;S<(1<<n);S++){
if(size[S]==1) continue;
edge[S]=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(i!=j && (S>>(i-1)&1) && (S>>(j-1)&1))
edge[S]+=e[i][j];
}
int cur=F(5);
printf("%d\n",(P+F((1<<n)-1))%P);
}
return 0;
}