[HEOI2013]SAO
题目大意:
一个有向无环图上有n个结点,
现在告诉你n-1个条件(x,y),表示x和y的先后关系。
问原图共有几种可能的拓扑序?
思路:
树形DP。
f[i][j]表示对于第i个结点,有j个点在它前面的方案数。
设当前结点为x,后面有一个结点为y,原本x前有i个结点,y前有j个结点,我们可以得到状态转移方程:
f[x][size[x]-i+size[y]-j]+=f[x][size[x]-i]*c[i+j][i]*c[size[x]-i+size[y]-j][size[y]-j]*((sum[y][size[y]]-sum[y][size[y]-j]+mod)%mod);
其中c是预处理好的组合数,sum是f数组的前缀和。
同样对于y在x前面的情况,状态转移方程如下:
f[x][i+j]+=f[x][i]*c[i+j][i]*c[size[x]-i+size[y]-j][size[y]-j]*sum[y][j];
最后就是求f[root][0]~f[root][n-1]的和,也就是sum[root][n]。
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
typedef long long int64;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=,mod=1e9+;
struct Edge {
int to;
bool type;
};
std::vector<Edge> e[N];
inline void add_edge(const int &u,const int &v,const bool &type) {
e[u].push_back((Edge){v,type});
e[v].push_back((Edge){u,!type});
}
int c[N][N];
inline void prep() {
for(register int i=;i<N;i++) {
c[i][]=;
for(register int j=;j<=i;j++) {
c[i][j]=(c[i-][j-]+c[i-][j])%mod;
}
}
}
int f[N][N],sum[N][N],size[N];
inline void init() {
memset(f,,sizeof f);
for(register int i=;i<N;i++) {
e[i].clear();
}
}
void dp(const int &x,const int &par) {
size[x]=;
f[x][]=;
for(unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i].to;
if(y==par) continue;
dp(y,x);
static int g[N];
memset(g,,sizeof g);
if(e[x][i].type) {
for(register int i=;i<=size[x];i++) {
for(register int j=;j<=size[y];j++) {
g[size[x]-i+size[y]-j]
+=(int64)f[x][size[x]-i]
*c[i+j][i]%mod
*c[size[x]-i+size[y]-j][size[y]-j]%mod
*((sum[y][size[y]]-sum[y][size[y]-j]+mod)%mod)%mod;
g[size[x]-i+size[y]-j]%=mod;
}
}
} else {
for(register int i=;i<=size[x];i++) {
for(register int j=;j<=size[y];j++) {
g[i+j]
+=(int64)f[x][i]
*c[i+j][i]%mod
*c[size[x]-i+size[y]-j][size[y]-j]%mod
*sum[y][j]%mod;
g[i+j]%=mod;
}
}
}
size[x]+=size[y];
memcpy(f[x],g,sizeof g);
}
size[x]++;
for(register int i=;i<=size[x];i++) {
sum[x][i]=(sum[x][i-]+f[x][i-])%mod;
}
}
int main() {
prep();
for(register int T=getint();T;T--) {
init();
const int n=getint();
for(register int i=;i<n;i++) {
const int u=getint(),sign=getchar(),v=getint();
add_edge(u,v,sign=='<');
}
dp(,-);
printf("%d\n",sum[][n]);
}
return ;
}
[HEOI2013]SAO的更多相关文章
- 3167: [Heoi2013]Sao [树形DP]
3167: [Heoi2013]Sao 题意: n个点的"有向"树,求拓扑排序方案数 Welcome to Sword Art Online!!! 一开始想错了...没有考虑一个点 ...
- 【BZOJ3167】[HEOI2013]SAO(动态规划)
[BZOJ3167][HEOI2013]SAO(动态规划) 题面 BZOJ 洛谷 题解 显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了). 那么考虑树型\(dp\),设\(f[i][ ...
- P4099 [HEOI2013]SAO
P4099 [HEOI2013]SAO 贼板子有意思的一个题---我()竟然没看题解 有一张连成树的有向图,球拓扑序数量. 树形dp,设\(f[i][j]\)表示\(i\)在子树中\(i\)拓扑序上排 ...
- BZOJ 3167: [Heoi2013]Sao
3167: [Heoi2013]Sao Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 96 Solved: 36[Submit][Status][D ...
- P4099 [HEOI2013]SAO(树形dp)
P4099 [HEOI2013]SAO 我们设$f[u][k]$表示以拓扑序编号为$k$的点$u$,以$u$为根的子树中的元素所组成的序列方案数 蓝后我们在找一个以$v$为根的子树. 我们的任务就是在 ...
- 【BZOJ3167/4824】[Heoi2013]Sao/[Cqoi2017]老C的键盘
[BZOJ3167][Heoi2013]Sao Description WelcometoSAO(StrangeandAbnormalOnline).这是一个VRMMORPG,含有n个关卡.但是,挑战 ...
- [HEOI2013]SAO(树上dp,计数)
[HEOI2013]SAO (这写了一个晚上QAQ,可能是我太蠢了吧.) 题目说只有\(n-1\)条边,然而每个点又相互联系.说明它的结构是一个类似树的结构,但是是有向边连接的,题目问的是方案个数,那 ...
- 【做题记录】 [HEOI2013]SAO
P4099 [HEOI2013]SAO 类型:树形 \(\text{DP}\) 这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...
- [HEOI2013]SAO ——计数问题
题目大意: Welcome to SAO ( Strange and Abnormal Online).这是一个 VR MMORPG, 含有 n 个关卡.但是,挑战不同关卡的顺序是一个很大的问题. 有 ...
- [BZOJ3167][P4099][HEOI2013]SAO(树形DP)
题目描述 Welcome to SAO ( Strange and Abnormal Online).这是一个 VR MMORPG, 含有 n 个关卡.但是,挑战不同关卡的顺序是一个很大的问题. 有 ...
随机推荐
- 旅游(CSUST省赛选拔赛2+状压dp+最短路)
题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...
- 2017ACM暑期多校联合训练 - Team 5 1001 HDU 6085 Rikka with Candies (模拟)
题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...
- 远程工具(SSH Secure)连接Centos出现中文乱码问题的解决办法
问题原因 使用远程工具进行连接时,如果linux有中文文件或目录,显示时会出现乱码,原因是linux编码是UTF-8,而远程工具默认是当前系统本地编码即GBK.所以解决方案是统一两者编码就OK了,但是 ...
- 73.Vivado使用误区与进阶——在Vivado中实现ECO功能
关于Tcl在Vivado中的应用文章从Tcl的基本语法和在Vivado中的应用展开,继上篇<用Tcl定制Vivado设计实现流程>介绍了如何扩展甚至是定制FPGA设计实现流程后,引出了一个 ...
- android的wake_lock介绍
Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的, 超时的锁会在时间过去以后自动解锁. 如果没有锁了或者 ...
- fullpage.js 具体使用方法
1.fullpage.js 下载地址 https://github.com/alvarotrigo/fullPage.js 2.fullPage.js 是一个基于 jQuery 的插件,它能够很方便 ...
- Django 1.10文档中文版Part1
目录 第一章.Django1.10文档组成结构1.1 获取帮助1.2 文档的组织形式1.3 第一步1.4 模型层1.5 视图层1.6 模板层1.7 表单1.8 开发流程1.9 admin站点1.10 ...
- day01作业
Java技术按照用途不同分为三大版本,分别是JavaSE.JavaEE和JavaMeJava虚拟机就是一个虚拟的用于执行字节码文件的计算机.它是Java最核心的技术,是Java跨平台的基础.DOS命令 ...
- 关于U3D中的移动和旋转
关于移动,其实很简单,就是移动: 第一个参数标识移动的距离,是一个矢量:第二个参数是因为游戏对象有自己的坐标系,还有一个世界坐标系,使用的坐标系不同将导致运动的结果不同: function Trans ...
- systemd基础
systemd 起源 systemd这一名字源于Unix中的一个惯例:在Unix中常以“d”作为系统守护进程(英语:daemon,亦称后台进程)的后缀标识.除此以外,systemd亦是借代英文术语D体 ...