题意

给定 \(n\) 个节点和 \(n-1\) 个限制,每个节点有一个权值,每个限制形如:\(a_i< a_j\) ,问有多少个 \(1\) 到 \(n\) 排列满足要求。

\(n\leq 1000\) 。

分析

  • 猜测复杂度为 \(O(n^2)\) ,并且应该要看成是树形结构。

  • 定义状态 \(f_{i,j}\) 表示以 \(i\) 为根的子树内有 \(j\) 个节点权值 \(< a_i\)的合法方案数。

  • 考虑转移,记 \(v\) 为 \(u\) 的儿子,有两种情况:

  • \(a_u > a_v\)

\[f_{u,j+k}=\binom{j+k}{k}\binom{{son}_u+{son}_v-1-j-k}{{son}_v-k}*f_{u,j}*\sum_{x=0}^{k-1}f_{v,x}
\]

  • \(a_u < a_v\)

\[f_{u,j+k}=\binom{j+k}{k}\binom{{son}_u+{son}_v-1-j-k}{{son}_v-k}*f_{u,j}*\sum_{x=k}^{{son}_v-1}f_{v,x}
\]

  • 总时间复杂度为 \(O(n^2)\) 。

代码

#include<bits/stdc++.h>
using namespace std;
#define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].last,v=e[i].to)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
#define re(x) memset(x,0,sizeof x)
typedef long long LL;
inline int gi(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
template<typename T>inline bool Min(T &a,T b){return b<a?a=b,1:0;}
const int N=1e3 + 7,mod=1e9 + 7;
int T,n,edc;
int head[N],c[N][N],f[N][N],s[N],son[N],g[N];
char str[10];
struct edge{
int last,to,c;
edge(){}edge(int last,int to,int c):last(last),to(to),c(c){}
}e[N*2];
void Add(int a,int b,int c){
e[++edc]=edge(head[a],b,c),head[a]=edc;
e[++edc]=edge(head[b],a,c^1),head[b]=edc;
}
void add(int &a,int b){a+=b;if(a>=mod) a-=mod;}
void init(){
re(head),re(f);edc=0;
}
void dfs(int u,int fa){
son[u]=f[u][0]=1;
go(u)if(v^fa){
dfs(v,u); re(s);re(g);
if(e[i].c==0){
for(int x=0;x<son[v];++x) s[x]=((x?s[x-1]:0)+f[v][x])%mod;
for(int tv=son[u]-1;~tv;--tv)
for(int b=son[v];b;--b)
add(g[tv+b],1ll*c[tv+b][b]*c[son[u]+son[v]-1-tv-b][son[v]-b]%mod*f[u][tv]%mod*s[b-1]%mod);
}else{
for(int x=son[v]-1;~x;--x) s[x]=(s[x+1]+f[v][x])%mod;
for(int tv=son[u]-1;~tv;--tv)
for(int b=son[v]-1;~b;--b)
add(g[tv+b],1ll*c[tv+b][b]*c[son[u]+son[v]-1-tv-b][son[v]-b]%mod*f[u][tv]%mod*s[b]%mod);
}
memcpy(f[u],g,sizeof g);
son[u]+=son[v];
}
}
void work(){
n=gi();
for(int i=1,a,b,c;i<n;++i){
scanf("%d%s%d",&a,str,&b);
c=str[0]=='>'?0:1;
Add(a+1,b+1,c);
}
dfs(1,0);int ans=0;
rep(i,0,n) add(ans,f[1][i]);
printf("%d\n",ans);
}
int main(){
rep(i,0,N-1){
c[i][0]=1;
rep(j,1,i) c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
T=gi();
while(T--) init(),work();
return 0;
}

[BZOJ3167][HEOI2013]SAO[树dp+组合数学]的更多相关文章

  1. 3167: [Heoi2013]Sao [树形DP]

    3167: [Heoi2013]Sao 题意: n个点的"有向"树,求拓扑排序方案数 Welcome to Sword Art Online!!! 一开始想错了...没有考虑一个点 ...

  2. [HEOI2013]SAO(树上dp,计数)

    [HEOI2013]SAO (这写了一个晚上QAQ,可能是我太蠢了吧.) 题目说只有\(n-1\)条边,然而每个点又相互联系.说明它的结构是一个类似树的结构,但是是有向边连接的,题目问的是方案个数,那 ...

  3. [BZOJ3167][P4099][HEOI2013]SAO(树形DP)

    题目描述 Welcome to SAO ( Strange and Abnormal Online).这是一个 VR MMORPG, 含有 n 个关卡.但是,挑战不同关卡的顺序是一个很大的问题. 有 ...

  4. bzoj3167 [Heoi2013]Sao

    传送门 这题神坑啊……明明是你菜 首先大家都知道原题等价于给每个点分配一个$1$~$n$且两两不同的权值,同时还需要满足一些大于/小于关系的方案数. 先看一眼数据范围,既然写明了$n\le 1000$ ...

  5. BZOJ 3167 [Heoi2013]Sao ——树形DP

    BZOJ4824的强化版. 改变枚举的方案,使用前缀和进行DP优化. 然后复杂度就是$O(n^2)$了. #include <map> #include <cmath> #in ...

  6. 洛谷 4099 [HEOI2013]SAO——树形DP

    题目:https://www.luogu.org/problemnew/show/P4099 结果还是看了题解才会…… 关键是状态,f[ i ][ j ] 表示 i 子树. i 号点是第 j 个出现的 ...

  7. 【BZOJ3167】[HEOI2013]SAO(动态规划)

    [BZOJ3167][HEOI2013]SAO(动态规划) 题面 BZOJ 洛谷 题解 显然限制条件是一个\(DAG\)(不考虑边的方向的话就是一棵树了). 那么考虑树型\(dp\),设\(f[i][ ...

  8. 【BZOJ3167/4824】[Heoi2013]Sao/[Cqoi2017]老C的键盘

    [BZOJ3167][Heoi2013]Sao Description WelcometoSAO(StrangeandAbnormalOnline).这是一个VRMMORPG,含有n个关卡.但是,挑战 ...

  9. P4099 [HEOI2013]SAO(树形dp)

    P4099 [HEOI2013]SAO 我们设$f[u][k]$表示以拓扑序编号为$k$的点$u$,以$u$为根的子树中的元素所组成的序列方案数 蓝后我们在找一个以$v$为根的子树. 我们的任务就是在 ...

随机推荐

  1. 如何获取UITableView中cell的frame值

    如何获取UITableView中cell的frame值 这个可以用来处理UITableView弹出键盘的问题 本人视频教程系类   iOS中CALayer的使用 效果: 源码: // // ViewC ...

  2. Linux su命令详解

    su switch user,用于切换用户用 su常见命令参数 用法:su [选项]... [-] [用户 [参数]... ] Change the effective user id and gro ...

  3. 设置邮箱发送服务|邮箱开始SMTP服务和腾讯云解封25端口的经验总结

    原文链接: http://www.lookdaima.com/WebForms/WebPages/Blanks/Pm/Docs/DocItemDetail.aspx?id=7dfaaf63-d36f- ...

  4. 第八章 计时器(BEEPER2)

    /*------------------------------------- BEEPER2.C -- Timer Demo Program No.1 (c) Charles Petzold, 19 ...

  5. virtualbox 错误解决记录

    1,E_INVALIDARG (0x80070057),virtualbox中Cannot register the hard disk错误解决办法 virtualbox中加载已有的虚拟硬盘时出现Ca ...

  6. jstorm知识整理

    最近在做一个jstorm的程序.我的jstorm程序消费一个kafka主题,根据数据逻辑判断需要往下游哪几个kafka主题的生产者发送. 1.bolt的execute(Tuple input)方法每次 ...

  7. 【[TJOI2015]弦论】

    \(SA+SAM\) 第一问显然是一个\(SAM\)的经典问题,我们排完序之后直接使用一直往下找\(n+1-sa[i]-het[i]\)就好了,找到\(K\)减不动了输出就好了 第二问是\(SAM\) ...

  8. salt常用命令(一)

    查看模块包含哪些函数 salt 'node' sys.list_functions test 查看函数的用法 salt 'node' sys.doc test.echo 使用模块中的函数 salt ' ...

  9. 统计Azure存储的HBase各表数据量

    场景:HBase存储在Azure上,现在通过访问Azure Storage的接口,获取HBase中各个表的数据量. 注意: 1.Azure存储,默认的副本数为2,即共存3份,但只收1份的费用,取到的s ...

  10. Lambda表达式学习(1)

    项目里面需要经常对一系列同类型集合进行操作 ,  如对集合进行增加元素 ,  删除集合的指定索引的元素等等.我们可以使用ArrayList来进行. 如 ArrayList stringArrayLis ...