BZOJ 3812主旋律

求一个图中强联通图的个数。

一看就是容斥啦,但这种二进制高端操作还是学习一下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 }
原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8612153.html