luogu P4099 [HEOI2013]SAO
这个依赖关系是个树,可以考虑树型dp,设f_i表示子树i的答案
因为这是个序列问题,是要考虑某个数的位置的,所以设\(f_{i,j}\)表示子树i构成的序列,i在第j个位置的方案.转移依次合并儿子\(y\),每次枚举一个位置j,以及枚举儿子\(y\)的序列中有k个数放在插前面,可以得到\(f_{x,j+k}\leftarrow f_{x,j}*w*\binom{j-1+k}{k}*\binom{sz_x+sz_y-j-k}{sz_y-k}\),组合数即考虑插入的方式
还有一个w不知道,如果要求\(x\)在\(y\)前面,那么\(y\)要在自己子树序列的\(k+1\)位置及以后所以\(w=\sum_{i=k+1}^{sz_y} f_{y,i}\),否则要在\(k\)及以前,所以\(w=\sum_{i=1}^{k} f_{y,i}\),显然可以记前缀和
最后答案为根的dp值总和.注意到合并复杂度,这些合并等价于每个点对都在lca处贡献一个\(O(1)\),所以总复杂度为\(O(n^2)\)
#include<bits/stdc++.h>
#define LL long long
#define db double
#define il inline
#define re register
using namespace std;
const int N=1000+10,mod=1e9+7;
il int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N<<1],nt[N<<1],w[N<<1],hd[N],tot=1;
il void add(int x,int y,int z)
{
++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],w[tot]=z^1,hd[y]=tot;
}
int c[N][N],f[N][N],g[N],sz[N],pr[N][N],sf[N][N];
void dp(int x,int ffa)
{
sz[x]=1;
f[x][1]=1;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(y==ffa) continue;
dp(y,x),sz[x]+=sz[y];
memset(g,0,sizeof(g));
if(w[i]==0)
{
for(int j=sz[x]-sz[y];j;--j)
for(int k=0;k<=sz[y];++k)
g[j+k]=(g[j+k]+1ll*f[x][j]*c[j-1+k][k]%mod*c[sz[x]-j-k][sz[y]-k]%mod*sf[y][k+1]%mod)%mod;
}
else
{
for(int j=sz[x]-sz[y];j;--j)
for(int k=0;k<=sz[y];++k)
g[j+k]=(g[j+k]+1ll*f[x][j]*c[j-1+k][k]%mod*c[sz[x]-j-k][sz[y]-k]%mod*pr[y][k]%mod)%mod;
}
memcpy(f[x],g,sizeof(g));
}
for(int i=1;i<=sz[x];++i) pr[x][i]=(pr[x][i-1]+f[x][i])%mod;
sf[x][sz[x]+1]=0;
for(int i=sz[x];i;--i) sf[x][i]=(sf[x][i+1]+f[x][i])%mod;
}
int main()
{
for(int i=0;i<=1000;++i)
{
c[i][0]=1;
for(int j=1;j<=i;++j) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
int T=rd();
while(T--)
{
memset(f,0,sizeof(f));
memset(hd,0,sizeof(hd)),tot=1;
int n=rd();
for(int i=1;i<n;++i)
{
int x=rd()+1,z=(getchar())=='>',y=rd()+1;
add(x,y,z);
}
dp(1,0);
int ans=0;
for(int i=1;i<=n;++i) ans=(ans+f[1][i])%mod;
printf("%d\n",ans);
}
return 0;
}
luogu P4099 [HEOI2013]SAO的更多相关文章
- P4099 [HEOI2013]SAO
P4099 [HEOI2013]SAO 贼板子有意思的一个题---我()竟然没看题解 有一张连成树的有向图,球拓扑序数量. 树形dp,设\(f[i][j]\)表示\(i\)在子树中\(i\)拓扑序上排 ...
- P4099 [HEOI2013]SAO(树形dp)
P4099 [HEOI2013]SAO 我们设$f[u][k]$表示以拓扑序编号为$k$的点$u$,以$u$为根的子树中的元素所组成的序列方案数 蓝后我们在找一个以$v$为根的子树. 我们的任务就是在 ...
- [BZOJ3167][P4099][HEOI2013]SAO(树形DP)
题目描述 Welcome to SAO ( Strange and Abnormal Online).这是一个 VR MMORPG, 含有 n 个关卡.但是,挑战不同关卡的顺序是一个很大的问题. 有 ...
- 洛谷 P4099 - [HEOI2013]SAO(树形 dp)
题面传送门 题意: 有一个有向图 \(G\),其基图是一棵树 求它拓扑序的个数 \(\bmod (10^9+7)\) \(n \in [1,1000]\) 如果你按照拓扑排序的方法来做,那恐怕你已经想 ...
- 洛谷P4099 [HEOI2013]SAO(树形dp)
传送门 HEOI的题好珂怕啊(各种意义上) 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关) 我们考虑 ...
- 洛谷$P4099\ [HEOI2013]\ SAO\ dp$
正解:树形$dp$ 解题报告: 传送门$QwQ$. 考虑设$f_i$表示点$i$的子树内的拓扑序排列方案数有多少个. 发现这样不好合并儿子节点和父亲节点.于是加一维,设$f_{i,j}$表示点$i$的 ...
- 【做题记录】 [HEOI2013]SAO
P4099 [HEOI2013]SAO 类型:树形 \(\text{DP}\) 这里主要补充一下 \(O(n^3)\) 的 \(\text{DP}\) 优化的过程,基础转移方程推导可以参考其他巨佬的博 ...
- 3167: [Heoi2013]Sao [树形DP]
3167: [Heoi2013]Sao 题意: n个点的"有向"树,求拓扑排序方案数 Welcome to Sword Art Online!!! 一开始想错了...没有考虑一个点 ...
- 【BZOJ3167】[HEOI2013]SAO(动态规划)
[BZOJ3167][HEOI2013]SAO(动态规划) 题面 BZOJ 洛谷 题解 显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了). 那么考虑树型\(dp\),设\(f[i][ ...
随机推荐
- 如何设置 ssh secure shell 支持中文
只需要设置下/etc/sysconfig/i18n 文件内容如清单 1 所示. 清单 1. 文件内容 1 2 3 LANG="zh_CN.GB18030" SUPPORTED=&q ...
- 如何写一个通用的README规范
背景 我们平常在进行项目开发时,一般都会把代码上传至代码托管平台上方便管理和维护.目前我厂使用的托管平台是SVN,国内外还有一些比较知名的代码托管平台,比如github.Gitlab.BitBucke ...
- [luogu2286][宠物收养所]
题目链接 思路 比较裸的一道平衡树的题.用一个变量S来表示当前树的情况,当S为负数时树内为宠物,当S为正数时树内为人.然后每次分情况讨论一下.如果树为空或者是与来的东西(人或宠物)与树内存的相同.那么 ...
- js 判断所选时间(或者当前时间)是否在某一时间段的实现代码
var time_range = function (beginTime, endTime, nowTime) { var strb = beginTime.split (":") ...
- px转换成bp单位的工具函数
import {Dimensions} from 'react-native' //当前屏幕的高度 const deviceH = Dimensions.get('window').height // ...
- 测试工程师的12最 作为测试猿的你是否都遇到过o_o ....
在51testing偶然看到一篇文章,觉得很不错,就转过来了.看完笑笑之后,如果能带来点思考就更好了. 1.测试工程师最开心的事:发现了一个很严重的bug,特别是那种隐藏很深,逻辑性的错误.偶第一次发 ...
- PHP冒泡排序算法
算法说明: 冒泡排序大概的意思是依次比较相邻的两个数,然后根据大小做出排序,直至最后两位数.由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序.但其实在实际过程中也可以根据 ...
- Day11--Python--函数名,闭包,迭代器
通过 lst.__iter__()拿到lst.的迭代器 1.函数名第一类对象 函数名就是变量名 1.函数名可以像变量一样互相赋值. 2.可以作为函数的参数,进行传递 3.可以作为返回值返回 4.可以作 ...
- 在gitlab新建空项目,将本地的git仓库的内容上传
gitlab新建了这个项目. 按照官网的步骤上传代码 一:将本地代码上传到本地仓库 1.进入项目文件夹 git init 2.项目代码添加到本地git git add . 3.提交到stage区域 g ...
- Python之偏函数
学前知识储备: 函数在Python是第一类对象 (Python中一切皆对象). 第一类对象的特性: ----1.可以被引用 ----2.可以当做参数传入 ----3.可以当做函数返回值 ----4.可 ...