当前位置: 首页 > news >正文

惠州东莞网站建设价格/互联网营销软件

惠州东莞网站建设价格,互联网营销软件,网站建设公司营销推广,做暖暖视频免费视频老司机网站传送门 n 个关卡有 n-1 个限制 所以这些限制构成一颗树 考虑树形DP 对一颗子树单独考虑 考虑有多少种顺序 设 f [ i ] 表示节点 i 的子树的总方案数 考虑儿子节点如何与父节点合并 发现父子之间有限制条件,所以 f 多加一维 f [ i ] [ j ] 表示节点 i 在子树中排第 j…

传送门

n 个关卡有 n-1 个限制

所以这些限制构成一颗树

考虑树形DP

对一颗子树单独考虑

考虑有多少种顺序

设 f [ i ] 表示节点 i 的子树的总方案数

考虑儿子节点如何与父节点合并

发现父子之间有限制条件,所以 f 多加一维 f [ i ] [ j ] 表示节点 i 在子树中排第 j 时的方案数

子树合并时就可以看成两个序列合并

比如像这样(x是v的父节点,x,v,是两颗子树的根):

  { ,,x,, } + { 。。v 。。。}  =  { ,。。,v 。x  ,  。。, }

上图就是 f [ x ] [ 3 ] 与 f [ v ] [ 3 ] 的一种合并方案 --> f [ x ] [ 7 ]

然后考虑方案数的增长

儿子的一部分合并到父节点左边,另一部分合并到父节点右边

对于父节点 x 和儿子节点 v

我们枚举合并后的父节点的排名 k ,枚举合并前的父节点排名 j,枚举儿子分离的中间点 o

儿子左半部分合并到父亲的方案有 C[ k-1 ] [ k-j ]

右部分合并父亲的方案有 C[ sz[x] - k ] [ sz[x]-sz[v]-j ](sz[ x ]此时已经包括sz [ v ])

然后可以得到完整的转移方程(不考虑父子关系的情况):  

$f_{xj}=\sum _{k=1}^{sz[x]}\sum_{j=1}^{min(sz[x]-sz[v],k)}\sum_{o=1}^{sz[v]}f_{xk}\times f_{vo}\times C_{k-1}^{k-j}\times C_{sz[x]-k}^{sz[x]-sz[v]-j}$

(sz是节点大小)

但这是O(n^3)的转移

优化十分显然,f [ v ] [ o ] 可以提出来用前缀和一起算,然后就是O(n^2)

然鹅我们还要考虑到父子间的限制...

那么如果 父节点要在子节点后   -->  k-j ≥ o ≥ 1

反之 sz[v] ≥ o > k-j

初始 f [ x ] [ 1 ] = 1 (合并前所有节点的子树只有它自己)

注意有多组数据,记得清空数组

实现看代码,要注意细节

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef unsigned long long ll;
inline int read()
{int x=0; char ch=getchar();while(ch<'0'||ch>'9') ch=getchar();while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }return x;
}
const int N=2e3+7,mo=1e9+7;
int fir[N],from[N<<1],to[N<<1],cnt;
inline void add(int &a,int &b)
{from[++cnt]=fir[a];fir[a]=cnt; to[cnt]=b;
}inline ll fk(ll x) { return x>=mo ? x-mo : x; }//这样取模会快一点
int n;
bool mp[N][N];//存父子间的大小关系
ll C[N][N];//组合数
void pre()//预处理组合数
{C[0][0]=1;for(int i=1;i<=n;i++)for(int j=0;j<=i;j++) C[i][j]=fk(C[i-1][j-1]+C[i-1][j]);
}
int sz[N];
ll f[N][N],g[N][N];//g是f的前缀和
void dfs(int x,int fa)
{for(int i=fir[x];i;i=from[i]){int &v=to[i]; if(v==fa) continue;dfs(v,x); sz[x]+=sz[v];for(int j=sz[x];j;j--)//注意j从大到小转移,先更新大的再更新小的
        {int L=min(sz[x]-sz[v],j); ll sum=0;for(int k=1;k<=L;k++){if(mp[x][v])//判断大小关系
                {int l=j-k,r=sz[v];//o的范围if(l<r)//注意边界
                    {ll t=( C[j-1][j-k] * C[sz[x]-j][sz[x]-sz[v]-k] )%mo;sum=fk(sum+( (f[x][k]*t)%mo * fk(g[v][r]+mo-g[v][l]) )%mo);}}else{int r=min(j-k,sz[v]); ll t=( C[j-1][j-k] * C[sz[x]-j][sz[x]-sz[v]-k] )%mo;sum=fk(sum+( (f[x][k]*t)%mo * g[v][r] )%mo);}}f[x][j]=sum;}}for(int i=1;i<=sz[x];i++) g[x][i]=fk(g[x][i-1]+f[x][i]);//计算前缀和
}
inline void clr()
{for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=g[i][j]=mp[i][j]=0;for(int i=1;i<=n;i++) sz[i]=f[i][1]=1/*注意*/,fir[i]=0;cnt=0;//cnt别忘了清空
}
int T;
int main()
{T=read();while(T--){int a,b; char c[5];n=read(); pre(); clr();for(int i=1;i<n;i++){a=read(); scanf("%s",c); b=read();a++; b++;add(a,b); add(b,a);if(c[0]=='<') mp[a][b]=1;else mp[b][a]=1;}dfs(1,1);ll ans=0;for(int i=1;i<=n;i++) ans=fk(ans+f[1][i]);printf("%lld\n",ans);}return 0;
}

 

转载于:https://www.cnblogs.com/LLTYYC/p/9809720.html

http://www.lbrq.cn/news/1323361.html

相关文章:

  • 网站一屏做多大/东莞网络推广及优化
  • 安防网站下载/网站seo公司哪家好
  • 机械网站建设注意什么/简述优化搜索引擎的方法
  • 潍坊寿光网站建设/站长之家字体
  • 做外贸首先要做网站/百度关键词推广一年多少钱
  • 怎么做网站咨询/最近一周新闻
  • wordpress收藏本站代码/网络推广深圳有效渠道
  • 做网站一个月30ip/世界杯32强排名
  • 网站和网页不同吗/最有效的广告宣传方式
  • 化妆品品牌策划方案/西安seo关键词排名优化
  • 青县网站建设公司/精准客户信息一条多少钱
  • 如何寻找做网站的客户/百度网盘账号登录入口
  • 天津网站优化公司/互联网推广平台有哪些
  • 商城建设开发/seo专员很难吗
  • 网站建设与规划实训总结/小程序自助搭建平台
  • asp网站转手机站/域名注册管理机构
  • 北京网站建设 乐云seo/百度站长工具验证
  • 在网上卖东西怎么找货源/广州seo优化推广
  • 宁波网站设计价格/电商sem是什么意思
  • 网站建设具体流程/搜索引擎有哪些?
  • 优化官方网站设计/重庆人力资源和社会保障网官网
  • 建设电子商务网站需要什么设备/凡科建站怎么样
  • 深圳网站建设小程序天安云谷/百度推广产品有哪些
  • 东莞网站网站建设/seo建站是什么意思
  • wordpress月亮花园/青岛seo全网营销
  • 软件项目网站建设实验报告/宁波抖音seo搜索优化软件
  • 用vuejs做网站/外贸独立站建站
  • 佛山小企业网站建设/怎么分析一个网站seo
  • 分销系统商城定制开发/seo排名优化怎么样
  • 国产服务器品牌前十大排名/优化视频
  • MFC CChartCtrl编程
  • wxPython 实践(五)高级控件
  • 常见CMS获取webshell的方法-靶场练习
  • Vulkan入门教程 | 第二部分:创建实例
  • K-近邻算法(KNN算法)的K值的选取--交叉验证+网格搜索
  • vue相关的拖拉拽官网