求一个图中强联通图的个数。
一看就是容斥啦,但这种二进制高端操作还是学习一下Candy?dalao
注释在代码里
好久没更了。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=(1<<16)+10,mod=1e9+7; 4 typedef long long ll; 5 int n,m,x,y,f[N],g[N],h[N],one[N],w[N],in[N],out[N]; 6 ll bin[N]; 7 int main() 8 { 9 scanf("%d%d",&n,&m); 10 for(int i=1;i<=m;++i) 11 { 12 scanf("%d%d",&x,&y); 13 out[1<<x-1]|=(1<<y-1);in[1<<y-1]|=(1<<x-1); 14 } 15 bin[0]=1; 16 for(int i=1;i<=m;++i)bin[i]=bin[i-1]*2%mod; 17 for(int s=1;s<1<<n;s++)one[s]=1+one[s^(s&-s)]; 18 for(int s=1;s<1<<n;s++){ 19 int p=s&-s,ns=s^p; 20 for(int t=ns;t;t=(t-1)&ns) 21 g[s]=(g[s]-1ll*f[s^t]*g[t]%mod)%mod; 22 h[s]=h[ns]+one[in[p]&ns]+one[out[p]&ns];//如何求一个诱导子图中边数 23 f[s]=bin[h[s]]; 24 for(int t=s;t;t=(t-1)&s){ 25 int p=(s^t)&-(s^t); 26 if(t==s)w[t]=0; 27 else w[t]=w[t^p]-one[out[p]&(s^t)]+one[in[p]&t];//求两个点集间的边数 28 f[s]=(f[s]-1ll*g[t]*bin[w[t]+h[s^t]]%mod)%mod; 29 } 30 if(f[s]<0)f[s]+=mod; 31 g[s]=(g[s]+f[s])%mod; 32 } 33 printf("%d",f[(1<<n)-1]); 34 return 0; 35 }