树形\(DP\)

考虑设\(f_{i,j,k}\)表示在\(i\)的子树内,从\(i\)向下的最长链长度为\(j\),\(i\)子树内直径长度为\(k\)的概率。

然后我们就能发现这个东西直接转移是几乎不可能的。

所以我们在转移时要开个辅助数组\(s_{op,x,y,k}\),其中\(op\)用于滚存,表示最长链为\(x\),次长链为\(y\),子节点子树内直径长度小于等于\(k\)的概率。

然后我们只要枚举子节点,再枚举子节点子树内的链长,就可以采用刷表法简便地\(DP\)转移了。

这样看似\(O(n^5)\),但如果你采用了记\(Size\)优化转移上界的方法,根据树上背包的复杂度,这里应该是\(O(n^4)\)的 。

最后我们更新\(f_{x,i,max(i+j,k)}\)加上\(s_{op,i,j,k}-s_{op,i,j,k-1}\)。

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 60
#define DB double
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
#define Gmax(x,y) (x<(y)&&(x=(y)))
using namespace std;
int n,ee,lnk[N+5];struct edge {int to,nxt;}e[N<<1];
class DpSolver
{
private:
int g[N+5],l[N+5];DB f[N+5][2*N+5][2*N+5],s[2][2*N+5][2*N+5][2*N+5];
I void DP(CI x,CI lst)
{
RI i,j,k,p,q,op;DB t,v;
for(g[x]=1,i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(DP(e[i].to,x),g[x]+=g[e[i].to]);//DP子节点
for(i=0;i<=2*g[x];++i) s[0][0][0][i]=1;//初始化
for(op=0,i=lnk[x];i;i=e[i].nxt) if(e[i].to^lst)//枚举子节点
{
for(j=0;j<=l[e[i].to];++j) for(k=1;k<=2*g[x];++k) f[e[i].to][j][k]+=f[e[i].to][j][k-1];//处理前缀和,方便转移
for(op^=1,j=0;j<=l[x];++j) for(k=0;k<=j;++k) for(p=0;p<=2*g[x];++p)//枚举当前状态
{
t=s[op^1][j][k][p],s[op^1][j][k][p]=0;//记下当前状态,注意清空原先数组
for(q=0;q<=l[e[i].to];++q) v=0.5*t*f[e[i].to][q][p],//枚举子树内最长链
q+1>j?(s[op][q+1][j][p]+=v):(q+1>k?s[op][j][q+1][p]+=v:s[op][j][k][p]+=v),//如果这条边长度为1
q+2>j?(s[op][q+2][j][p]+=v):(q+2>k?s[op][j][q+2][p]+=v:s[op][j][k][p]+=v);//如果这条边长度为2
}Gmax(l[x],l[e[i].to]+2);
}
for(i=0;i<=l[x];++i) for(j=0;j<=i;++j) for(k=2*g[x];~k;--k)//枚举状态
f[x][i][max(i+j,k)]+=s[op][i][j][k]-(k?s[op][i][j][k-1]:0),s[op][i][j][k]=0;//将状态更新到f数组中,并清空
}
public:
I void Solve()
{
RI i,j;DB ans=0;DP(1,0);//树形DP
for(i=0;i<=l[1];++i) for(j=i;j<=2*g[1];++j) ans+=f[1][i][j]*j;//统计答案
printf("%.8lf",ans);//输出答案
}
}D;
int main()
{
freopen("tree.in","r",stdin),freopen("tree.out","w",stdout);
RI i,x,y;for(scanf("%d",&n),i=1;i^n;++i) scanf("%d%d",&x,&y),add(x,y),add(y,x);//读入建边
return D.Solve(),0;
}

【2019.8.20 NOIP模拟赛 T2】小B的树(tree)(树形DP)的更多相关文章

  1. 【2019.7.20 NOIP模拟赛 T2】B(B)(数位DP)

    数位\(DP\) 首先考虑二进制数\(G(i)\)的一些性质: \(G(i)\)不可能有连续两位第\(x\)位和第\(x+1\)位都是\(1\).因为这样就可以进位到第\(x+2\)位.其余情况下,这 ...

  2. 【2019.7.15 NOIP模拟赛 T2】与非树(nand)(树形DP)

    树形\(DP\) 实际上,这道题应该不是很难. 我们设\(f_{x,i,j}\)表示在以\(x\)为根的子树内,原本应输出\(i\),结果输出了\(j\)的情况数. 转移时,为了方便,我们先考虑与,再 ...

  3. 【2019.8.20 NOIP模拟赛 T3】小X的图(history)(可持久化并查集)

    可持久化并查集 显然是可持久化并查集裸题吧... 就是题面长得有点恶心,被闪指导狂喷. 对于\(K\)操作,直接\(O(1)\)赋值修改. 对于\(R\)操作,并查集上直接连边. 对于\(T\)操作, ...

  4. 【2019.7.20 NOIP模拟赛 T1】A(A)(暴搜)

    打表+暴搜 这道题目,显然是需要打表的,不过打表的方式可以有很多. 我是打了两个表,分别表示每个数字所需的火柴棒根数以及从一个数字到另一个数字,除了需要去除或加入的火柴棒外,至少需要几根火柴棒. 然后 ...

  5. 【2019.7.16 NOIP模拟赛 T2】折叠(fold)(动态规划)

    暴力\(DP\) 考虑暴力\(DP\),我们设\(f_{i,j}\)表示当前覆盖长度为\(i\),上一次折叠长度为\(j\)的方案数. 转移时需要再枚举这次的折叠长度\(k\)(\(k\ge j\)) ...

  6. 【2019.8.6 慈溪模拟赛 T2】树上路径(tree)(Trie)

    从暴力考虑转化题意 考虑最暴力的做法,我们枚举路径的两端,然后采用类似求树上路径长度的做法,计算两点到根的贡献,然后除去\(LCA\)到根的贡献两次. 即,设\(v_i\)为\(i\)到根路径上的边权 ...

  7. 2019.7.26 NOIP 模拟赛

    这次模拟赛真的,,卡常赛. The solution of T1: std是打表,,考场上sb想自己改进匈牙利然后wei了(好像匈牙利是错的. 大力剪枝搜索.代码不放了. 这是什么神仙D1T1,爆蛋T ...

  8. 20161003 NOIP 模拟赛 T2 解题报告

    Weed duyege的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹. 为了查出真相,duyege 准备修好电脑之后再进行一次金坷垃的模拟实验. 电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为 ...

  9. 2018.02.12 noip模拟赛T2

    二兵的赌注 Description游戏中,二兵要进入了一家奇怪的赌场.赌场中有n个庄家,每个庄家都可以猜大猜小,猜一次一元钱.每一次开彩前,你都可以到任意个庄家那里下赌注.如果开彩结果是大,你就可以得 ...

随机推荐

  1. Symfonos:3 Vulnhub Walkthrough

    主机扫描: ╰─ nmap -p1-65535 -sV -A -sT 10.10.202.130 Starting Nmap 7.70 ( https://nmap.org ) at 2019-08- ...

  2. IDEA新建servlet时出现的错误

    未注入Tomcat里lib文件下的jar 这样即可

  3. socket简单介绍

    一 三种类型的套接字: 1.流式套接字(SOCKET_STREAM)     提供面向连接的可靠的数据传输服务.数据被看作是字节流,无长度限制.例如FTP协议就采用这种. 2.数据报式套接字(SOCK ...

  4. Cocos2d-x游戏实例《忍者飞镖》之对象管理

    推荐移步至<忍者飞镖射幽灵>之对象管理阅读 配置环境:win7+Cocos2d-x.2.0.3+VS2012 目标读者:需了解游戏帧率以及回调函数的概念 一.引言 对具体游戏demo的分析 ...

  5. 编辑器之神vim的一些常用快捷键整理

    yy:复制 光标所在的这一行 4yy:复制 光标所在行开始向下的4行 p:粘贴 dd:剪切(删除) 光标所在的这一行 4dd:剪切(删除) 光标所在行向下的4行 D:从当前的光标开始向后剪切,一直到行 ...

  6. [洛谷P1122][题解]最大子树和

    这是一道还算简单的树型dp. 转移方程:f[i]=max(f[j],0) 其中i为任意非叶节点,j为i的一棵子树,而每棵子树都有选或不选两种选择 具体看代码: #include<bits/std ...

  7. ccf-csp201809题解

    目录 ccf-csp201809题解 1. 201809-1 卖菜 题目描述 解析 通过代码 2. 201809-2 买菜 题目描述 解析 通过代码 3.201809-3 元素选择器 题目描述 解析 ...

  8. Flutter中高级培训

    Flutter中高级培训 一.简介 Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面.Flutter可以与现有的代码一起工作.本课程全面介绍Flutter ...

  9. Linux系统:centos7下搭建Rocketmq4.3中间件,配置监控台

    本文源码:GitHub·点这里 || GitEE·点这里 一.环境搭建 环境版本 centos7 jdk1.8 已搭建好 rocketmq4.3 1.下载安装包 网址 https://www.apac ...

  10. RabbitMQ与Spring的框架整合之Spring Cloud Stream实战

    1.RabbitMQ与Spring Cloud Stream整合实战.SpringCloud Stream整体结构核心概念图,如下所示: 图示解释:Outputs输出,即消息的发送端.Inputs输入 ...