2017.11.3 树上期望DP 解题报告
来源:互联网 发布:linux改用户名命令 编辑:程序博客网 时间:2024/06/07 00:38
题目描述
梦游中的你来到了一棵N个节点的树上. 你一共做了Q个梦, 每个梦需要你从点u走到点v之后才能苏醒, 由于你正在梦游, 所以每到一个节点后,你会在它连出去的边中等概率地选择一条走过去, 为了确保第二天能够准时到校, 你要求出每个梦期望经过多少条边才能苏醒. 为了避免精度误差, 你要输出答案模109+7的结果.
输入格式
第一行两个整数分别代表N和Q. 接下来N-1行, 每行两个整数u, v代表树中的一条边. 接下来Q行, 每行两个整数代表询问的u,v.
输出格式
一共Q行, 每行一个整数代表答案.
样例
tree.in
4 2
1 2
2 3
3 4
1 4
3 4
tree.out
9
5
数据范围
对于20%的数据, N <= 10.
对于40%的数据, N <= 1000.
另有20%的数据, 保证给定的树是一条链.
对于100%的数据, N <= 100000, Q <= 100000.
【解题报告】
这个小树什么的是骗你的。
我们定义
那么显然
我们接着定义
我们可以的得到
一种证明方式http://blog.csdn.net/V5ZSQ/article/details/52314029
直接DP转移即可
代码如下:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long long#define N 100010#define mod 1000000007int n,q,cnt=-1,head[N];struct Edge{int to,nxt;}e[N<<1];int size[N];LL down[N],up[N];void adde(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; e[++cnt].to=u;e[cnt].nxt=head[v];head[v]=cnt;}namespace LCA{ int dis[N],ff[18][N]; void dfs(int p,int father) { dis[p]=dis[father]+1,ff[0][p]=father; for(int i=head[p];~i;i=e[i].nxt) { int v=e[i].to; if(v^father) dfs(v,p); } } void da() { for(int j=1;(1<<j)<=n;++j) for(int i=1;i<=n;++i) ff[j][i]=ff[j-1][ff[j-1][i]]; } int query(int x,int y) { if(dis[x]<dis[y]) x^=y^=x^=y; int t=dis[x]-dis[y]; for(int i=0;i<=17;++i) if(t&(1<<i)) x=ff[i][x]; if(x==y) return x; for(int i=17;~i;--i) if (ff[i][x]^ff[i][y]) x=ff[i][x],y=ff[i][y]; return ff[0][x]; }}namespace DP{ void dfs1(int u,int fa)//size { size[u]=1; for(int i=head[u];~i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue; dfs1(v,u); size[u]+=size[v]; } } void dfs2(int u,int fa)//down&up(pre_sum!!!) { for(int i=head[u];~i;i=e[i].nxt) { int v=e[i].to; if(v==fa) continue; up[v]=2*size[v]-1+up[u]; down[v]=2*n-2*size[v]-1+down[u]; dfs2(v,u); } }}using namespace LCA;using namespace DP;int main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); memset(head,-1,sizeof(head)); scanf("%d%d",&n,&q); for(int i=1,u,v;i<n;++i) { scanf("%d%d",&u,&v); adde(u,v); } dfs(1,1); dfs1(1,1); up[1]=0;down[1]=0; dfs2(1,1); da();// for(int i=1;i<=n;++i) printf("%d %d\n",up[i],down[i]); for(int i=1,u,v;i<=q;++i) { scanf("%d%d",&u,&v);// printf("%d %d ",u,v); int tmp=query(u,v);//printf(" %d ",tmp);// printf("%d ",tmp); long long ans=up[u]+down[v]-up[tmp]-down[tmp]; printf("%lld\n",ans%mod); } return 0;}/*4 21 22 33 41 43 4*/
阅读全文
0 0
- 2017.11.3 树上期望DP 解题报告
- 2017.11.2 树上期望DP 解题报告
- BZOJ 3566 [SHOI 2014] 树上期望DP 解题报告
- BZOJ4033[HAOI2015] 树上染色 解题报告【树上DP】
- HDU 5781 数学期望+DP 解题报告
- BZOJ 4318 期望DP 解题报告
- bzoj 4318 期望DP 解题报告
- BZOJ4318 OUS! 解题报告【期望DP】
- ZOJ 3329 期望DP 解题报告
- poj 2096 期望DP 解题报告
- BZOJ 2201 期望DP 解题报告
- Codeforces 24D 期望DP 解题报告
- 2017.11.2 支配树上LCA 解题报告
- 树上操作 解题报告
- 解题报告:POJ_1155 TELE 树型DP(树上01背包)
- Hdu 1561 The more, The Better 树上DP 解题报告
- HDU1561 The more, The Better 解题报告【树上DP/背包】
- Tree (树上期望dp)
- 数据结构-树与二叉树
- python网络爬虫系列教程——Python+PhantomJS +Selenium组合应用
- PHP连接和拆分数组array_combine()和array_slice()用法示例
- 2017年11月3日博客开通随笔
- Essential Studio for Xamarin更新至2017 v3版本,增加新的选择器控件丨附下载
- 2017.11.3 树上期望DP 解题报告
- 使用Merge引擎
- 添加购物车弧形动画
- git学习之:eclipse项目提交到gitHub
- Retrofit联网报错:Retrofit: Invalid % sequence at XXXX的解决方法
- Linux+Nginx+php7 redis扩展安装
- 用Delphi+DirectShow实现的视频播放器,可用于游戏片头播放
- union all 和where条件一起使用查询数据不对的问题
- 消息队列的使用场景