题目描述

给定一个\(DAG\),问这个\(DAG\)有多少种拓扑序。

题解

我们首先需要设计一个能够比较好的转移的状态。

我们可以设\(dp[i][j]\)表示第i个点在当前\(dp\)的子图中拓扑排名为\(j\)的方案数。

至于\(dp\)的方式,我们发现只有\(n-1\)条边,所以我们并不用在\(DAG\)上\(dp\),直接在建出来的树上\(dp\)就好了。

转移的话,对于一条树边\(u->v\)我们先枚举转移之后的\(u\)的排名,再枚举当前\(v\)的排名,我们发现还需要枚举\(v\)的子树在\(u\)排名之前的点的个数\(x\)。

当\(u\)需要在\(v​\)之后时:

\[dp[u][j]=\sum_{k=1}^{k\leq size[v]}\sum_{x=k}^{x\leq size[v]}dp[u][j-x]*\binom{j-1}{x}*\binom{size[u]-(j-x)+size[v]-x}{size[v]-x}
\]

发现转移是一个后缀和的形式,可以用后缀和优化)。

当\(u\)需要在\(v\)之前时。

\[dp[u][j]=\sum_{k=1}^{k\leq size[v]}\sum_{x=1}^{x<k}dp[u][j-x]*\binom{j-1}{x}*\binom{size[u]-(j-x)+size[v]-x}{size[v]-x}
\]

转移是一个前缀和的形式,也可以用前缀和优化。

经过优化后,这个\(dp\)的复杂度可以优化到树形背包的复杂度,也就是\(O(n^2)\)。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1009
using namespace std;
typedef long long ll;
const int maxn=1000;
const int mod=1000000007;
char s[1];
ll ans,dp[N][N],now[N],c[N][N],g[N];
int tot,head[N],size[N],n;
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
inline void MOD(ll &x){x=x>=mod?x-mod:x;}
struct edge{int n,to,l;}e[N<<1];
inline void add(int u,int v,int l){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;}
void dfs(int u,int fa){
size[u]=1;
dp[u][1]=1;
for(int i=head[u];i;i=e[i].n){
int v=e[i].to;if(v==fa)continue;
dfs(v,u);
if(e[i].l){
for(int j=1;j<=size[u]+size[v];++j){
int ma=min(size[v],j-1);
now[ma+1]=0;
for(int x=ma;x>=1;--x)
MOD(now[x]=now[x+1]+dp[u][j-x]*c[j-1][x]%mod*c[size[u]-(j-x)+size[v]-x][size[v]-x]%mod);
for(int k=1;k<=size[v];++k)MOD(g[j]+=dp[v][k]*now[k]%mod),now[k]=0;
}
}
else{
for(int j=1;j<=size[u]+size[v];++j){
int ma=min(size[v],j-1);
for(int x=0;x<=ma;++x)
MOD(now[x]=now[x-1]+dp[u][j-x]*c[j-1][x]%mod*c[size[u]-(j-x)+size[v]-x][size[v]-x]%mod);
for(int k=1;k<=size[v];++k)MOD(g[j]+=now[min(k-1,ma)]*dp[v][k]%mod);
for(int x=0;x<=ma;++x)now[x]=0;
}
}
size[u]+=size[v];
for(int j=1;j<=size[u];++j)dp[u][j]=g[j],g[j]=0;
}
}
int main(){ // 1 -> dayu 0 -> xiaoyu
int T=rd();
c[0][0]=1;
for(int i=1;i<=maxn;++i){
c[i][0]=1;
for(int j=1;j<=i;++j)MOD(c[i][j]=c[i-1][j]+c[i-1][j-1]);
}
while(T--){
n=rd();int u,v;
memset(dp,0,sizeof(dp));
memset(head,0,sizeof(head));tot=0;
for(int i=1;i<n;++i){
u=rd()+1;scanf("%s",s);v=rd()+1;
add(u,v,s[0]=='>');add(v,u,s[0]=='<');
}
ans=0;dfs(1,0);
for(int i=1;i<=n;++i)MOD(ans+=dp[1][i]);
printf("%lld\n",ans);
}
return 0;
}

HEOI2013SAO的更多相关文章

  1. BZOJ3167/BZOJ4824 HEOI2013SAO/CQOI2017老C的键盘(树形dp)

    前者是后者各方面的强化版. 容易想到设f[i][j]表示i子树中第j小的是i的方案数(即只考虑相对关系).比较麻烦的在于转移.考虑逐个合并子树.容易想到枚举根原来的排名和子树根原来的排名,算一发组合数 ...

  2. CodeChef LEMOVIE

    题意:给你n个数字(下标不同数值相同的数字应当被认为是不同的数字),有n!种排列方式.每种排列方式的价值定义为:第一次出现时比前面的所有数字都大的数值个数. 比如1,2,2,3这个排列中,1,2,3这 ...

随机推荐

  1. c# 图片加水印

    /// <summary> /// 图片水印 /// </summary> /// <param name="imgPath">服务器图片相对路 ...

  2. 多线程之Thread

    Thread类可以创建和控制线程,Thread类的构造函数重载为接受ThreadStart和ParameterizedThreadStart类型的委托参数. Thread类默认创建的是前台线程,所以我 ...

  3. 20190423-Vscode与Sass不得不说的秘密(>^ω^<)

    这是乱七八糟的前言:emmm,今天倔强的点,是关于Vscode使用easySass插件时,不安装ruby环境,直接使用插件编译时,不进行设置,分音是会转译为Css文件的= =,神坑的后知后觉才发现是因 ...

  4. React create-react-app Build fails after eject: Cannot find module '@babel/plugin-transform-react-jsx'

    运行 npm run eject 出现报错 Build fails after eject: Cannot find module '@babel/plugin-transform-react-jsx ...

  5. C# 通过KD树进行距离最近点的查找.

    本文首先介绍Kd-Tree的构造方法,然后介绍Kd-Tree的搜索流程及代码实现,最后给出本人利用C#语言实现的二维KD树代码.这也是我自己动手实现的第一个树形的数据结构.理解上难免会有偏差,敬请各位 ...

  6. Python3 调试技巧 —— 死循环

    说下Python3不使用gdb的自身调试 前情提要:服务器莫名卡死,用网上的方法用gdb,下载了很多组件,包括那个libpython.py,都没什么用,看不到堆栈,也试了保存core文件等等 大事找官 ...

  7. python datetime操作

    #datetime object转化为timestamp import datetime now = datetime.datetime.now() now_timestamp = time.mkti ...

  8. 从0开始的Python学习013编写一个Python脚本

    通过之前的学习我们已经了解了Python的很多基础运用了,现在我们尝试着做一个有使用价值的小脚本. 问题 需求: 我想要一个可以给我备份重要文件的程序. 需求分析: 首先文件是有存储路径,文件的路径和 ...

  9. 分布式缓存Redis集群配置使用

    Redis 简介          redis是一种开源的.基于内存的.可持久化的.高性能的Key-Value数据存储系统. redis能做什么? 持久化存储  高速缓存 消息中间件         ...

  10. WPF软件开发系统之二——水环境检测Surface触摸屏软件开发

    该系统采用C#.WPF语言开发,开发工具Visual Studio 2015.Blend,环境WIN7系统及以上,适用于PC.Windows触摸屏Surface等设备. 部分截图效果如下: 开发工具环 ...