分析

Miskcoo orz

令$f[S]$表示使得$S$这个点集强连通的方案数。

然后呢?不会了

考虑到将一个有向图SCC缩点后,得到的新图是一个DAG,所以我们可以类比带标号DAG计数的解法来寻找这道题的突破口。

我们可以枚举哪些点所构成的SCC在缩点后入度为$0$,然后令$g[S]$表示使$S$这个点集缩点后是一堆强连通分量且之间不存在边的方案数(不然入度就不是$0$了),可以得到下面这个递推式:

\(f[S]=2^{cnt[S]}-\sum_{T \subseteq S,T \neq \emptyset}2^{cnt[S-T]+to[T][S-T]} \times g[T]\)

这个递推式显然是错的(辣鸡博主欺骗感情),因为一个有向图SCC缩点后会出现多个入度为$0$的点。在带标号DAG计数I中,我们选择使用小学奥数容斥解决重复计数的问题,这里同样如此。但是我们发现,这里是加是减取决于度数为$1$的SCC的个数而并非是点数,因此这个容斥过程很难通过正常方法实现。

~~考虑上网搜题解,~~我们会发现一个很神奇的操作,我们可以让容斥在计算$g[T]$的过程中完成。如果不能理解的话,我们可以看一看$g$数组的递推式:

\(g[S]=f[S]+\sum_{T \subsetneq S,u \notin T,T \neq \emptyset}f[S-T] \times g[T]\)

(P.S.这里用到了一个trick,就是通过枚举编号最小的点所在SCC防止重复统计,不过这个trick貌似拯救不了之前那个错误的递推式)

原本是长这个样子的,不过我们可以稍作修改:

\(g[S]=f[S]-\sum_{T \subsetneq S,u \notin T,T \neq \emptyset}f[S-T] \times g[T]\)

这里把加号变成了减号,含义大概就是每新加入一个SCC,符号就要变化(即取相反数)。

然后$cnt[S]$和$to[S][T]$数组的处理都很简单就不扯这么多了。

好神仙啊。

代码

#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
#define lowbit(x) ((x)&(-(x)))
#define r (s^t)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int MAXN=20;
const LL MOD=1e9+7; int n,m,inE[1<<15],outE[1<<15];
int popcnt[1<<15];
LL f[1<<15],g[1<<15],cnt[1<<15],to[1<<15];
LL pow2[230]; int main(){
n=read(),m=read();
pow2[0]=1;
rin(i,1,225) pow2[i]=(pow2[i-1]<<1)%MOD;
rin(i,1,m){
int u=read()-1,v=read()-1;
inE[1<<v]|=(1<<u);
outE[1<<u]|=(1<<v);
}
rin(i,0,(1<<n)-1) popcnt[i]=__builtin_popcount(i);
rin(s,1,(1<<n)-1){
int x=lowbit(s),y=(s^x);
cnt[s]=cnt[y]+popcnt[inE[x]&s]+popcnt[outE[x]&s];
for(register int t=s;t;t=((t-1)&s)){
if(t==s){to[t]=0;continue;}
int xx=lowbit(r);
to[t]=to[t^xx]-popcnt[outE[xx]&r]+popcnt[inE[xx]&t];
}
for(register int t=y;t;t=((t-1)&y)) g[s]=(g[s]-f[r]*g[t]%MOD+MOD)%MOD;
f[s]=pow2[cnt[s]];
for(register int t=s;t;t=((t-1)&s)) f[s]=(f[s]-pow2[cnt[r]+to[t]]*g[t]%MOD+MOD)%MOD;
g[s]=(g[s]+f[s])%MOD;
}
printf("%lld\n",f[(1<<n)-1]);
return 0;
}

[BZOJ3812]主旋律:状压DP+容斥原理的更多相关文章

  1. 【uoj#37/bzoj3812】[清华集训2014]主旋律 状压dp+容斥原理

    题目描述 求一张有向图的强连通生成子图的数目对 $10^9+7$ 取模的结果. 题解 状压dp+容斥原理 设 $f[i]$ 表示点集 $i$ 强连通生成子图的数目,容易想到使用总方案数 $2^{sum ...

  2. 【bzoj2560】串珠子 状压dp+容斥原理

    题目描述 有 $n$ 个点,点 $i$ 和点 $j$ 之间可以连 $0\sim c_{i,j}$ 条无向边.求连成一张无向连通图的方案数模 $10^9+7$ .两个方案不同,当且仅当:存在点对 $(i ...

  3. BZOJ2669 [cqoi2012]局部极小值 状压DP 容斥原理

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2669 题意概括 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所 ...

  4. 4455: [Zjoi2016]小星星|状压DP|容斥原理

    OrzSDOIR1ak的晨神 能够考虑状压DP枚举子集,求出仅仅保证连通性不保证一一相应的状态下的方案数,然后容斥一下就是终于的答案 #include<algorithm> #includ ...

  5. 【BZOJ 2669】 2669: [cqoi2012]局部极小值 (状压DP+容斥原理)

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 667  Solved: 350 Description 有一 ...

  6. BZOJ3812 主旋律(状压dp+容斥原理)

    设f[S]为S点集是SCC的方案数.考虑通过去掉不合法方案转移.可以枚举入度为0的SCC所含点集S',这样显然S^S'内部的边和由S'连向S^S'的边删还是不删任选.但是这样无法保证S'包含所有入度为 ...

  7. HDU5838 Mountain(状压DP + 容斥原理)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5838 Description Zhu found a map which is a N∗M ...

  8. 【BZOJ-2669】局部极小值 状压DP + 容斥原理

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 561  Solved: 293[Submit][Status ...

  9. BZOJ 2669 CQOI2012 局部极小值 状压dp+容斥原理

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2669 题意概述:实际上原题意很简洁了我就不写了吧.... 二话不说先观察一下性质,首先棋盘 ...

随机推荐

  1. FESCAR

    FESCAR:阿里重磅开源分布式事务解决方案 FESCAR名字的由来:Fast & EaSy Commit And Rollback FESCAR是啥? 被用在微服务架构中的高性能分布式事务解 ...

  2. 一台 Java 服务器可以跑多少个线程?

    一台Java服务器能跑多少个线程? 这个问题来自一次线上报警如下图,超过了我们的配置阈值. 京东自研UMP监控分析 打出jstack文件,通过IBM Thread and Monitor Dump A ...

  3. 移除list里面的值

    public class IteratorTest { public static void main(String[] args) { List<String> list = new A ...

  4. 【提高组NOIP2008】双栈排序 (twostack.pas/c/cpp)

    [题目描述] Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈 ...

  5. 多线程之小米商店APP爬虫

    #今日目标 **多线程之小米商店APP爬虫** 爬取小米商店所有社交APP ``` import requests import time from threading import Thread f ...

  6. 一分钟理解sdk

    SDK 外语:Software Development Kit 中文:软件开发工具包 含义:一般都是一些软件工程师为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件时的开发工具的集合. 通俗: ...

  7. vue-element-ui upload组件调用两次接口

    在使用upload中,默认是自动上传,会发现会调用两次接口,一次是Request Method: OPTIONS且不带任何参数(群里大佬说是跨域 预检测),一次是Request Method: POS ...

  8. this 到底指向谁

    this 的指向,是在调用函数时根据执行上下文所动态确定的. 在函数体中,简单调用该函数时(非显式/隐式绑定下),严格模式下 this 绑定到 undefined,否则绑定到全局对象 window/g ...

  9. Spring Boot自定义Redis缓存配置,保存value格式JSON字符串

    Spring Boot自定义Redis缓存,保存格式JSON字符串 部分内容转自 https://blog.csdn.net/caojidasabi/article/details/83059642 ...

  10. 基于AliOS的车载小程序

    4月16日上海国际车展首日,阿里巴巴表示正在研发基于AliOS的车载小程序.同时还展出AI HUD.AI驾驶舱等最新技术,AliOS表示正在构建一个可持续发展的整合平台. 阿里方面表示,作为小程序在车 ...