(n17)
SOL:
采用容斥,至多n-1个公司-至多n-2个公司+至多n-3个公司……
用二进制数枚举每个公司是否选取,然后用矩阵树定理求行列式算出方案
时间复杂度(O(2^nn^3))
注意数组大小
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
#define ll long long
const int N=20,M=1<<17,mod=1e9+7;
inline int ksm(int x,int r){
int ret=1;
for(int i=0;(1<<i)<=r;i++){
if((r>>i)&1)ret=(ll)ret*x%mod;
x=(ll)x*x%mod;
}
return ret;
}
int n,S,ans,m[N],a[N][N],u[N][504],v[N][504],sz[M];
inline int det(){
int ret=1,fl=0;
for(int i=1;i<n;i++){
if(!a[i][i]){
for(int j=i+1;j<n;j++)
if(a[j][i]){
swap(a[i],a[j]);fl^=1;
break;
}
}
if(!a[i][i])return 0;
for(int j=i+1,inv=ksm(a[i][i],mod-2),tmp;j<n;j++){
if(!a[j][i])continue;
tmp=(ll)a[j][i]*inv%mod;
for(int k=i;k<n;k++)a[j][k]=(a[j][k]-(ll)a[i][k]*tmp%mod+mod)%mod;
}
}
for(int i=1;i<n;i++)ret=(ll)ret*a[i][i]%mod;
return fl?(mod-ret)%mod:ret;
}
int main(){
n=read();S=(1<<n-1)-1;
for(int i=1;i<n;i++){
m[i]=read();
for(int j=1;j<=m[i];j++){
u[i][j]=read();v[i][j]=read();
}
}
for(int s=1,uu,vv;s<=S;s++){
memset(a,0,sizeof(a));
for(int i=1;i<n;i++){
if(!((s>>i-1)&1))continue;
for(int j=1;j<=m[i];j++){
uu=u[i][j];vv=v[i][j];
a[uu][uu]++;a[vv][vv]++;
a[uu][vv]=(a[uu][vv]+mod-1)%mod;a[vv][uu]=(a[vv][uu]+mod-1)%mod;
}
}
sz[s]=sz[s>>1]+(s&1);
ans=((ll)ans+mod+(((n-sz[s])%2)?det():-det()))%mod;
}
cout<<ans;
return (0-0);
}