数据结构作业——expectation(树形dp+dfs)
expectation
Description
给出一棵带权值的树,我们假设从某个节点出发,到目标节点的时间为两个节点之间的最短路。由于出发节点不好选取,所以选在每个节点都有一定的概率,现在我们要求从出发点到目标节点的期望时间(即每个节点到目标点的时间*概率)。 为了避免精度错误, 直接给出了每个节点所占的权值, 那么每个节点的概率就是节点权值/总权值和( 注意查看实际输出要求)。
Input
输入第一行为一个正整数 n 表示树的节点数目, 节点编号从 1 到 n。
接下来一行 n 个整数 vi, 表示第 i 个节点所占的权值(<=20)。 紧接着 n-1 行,每行三个数 x, y, d (d<=20) ,表示经过 x 和 y 之间的树边 所需花费的时间为 d。
接下来一行有一个整数 q,表示询问数目。 紧接着 q 行, 每行一个整数,表示目的节点。
30%的数据: n<=20,q=1
50%的数据: n<=1000, q<=10
80%的数据: n<=10000,q<=1000 100%的数据: n<=100000, q<=n
Output
Sample Input
- 51 1 1 1 11 2 21 3 11 4 33 5 21 3
Sample Output
- 10
思路
每个节点保存两个值,一个是其子树的点权和(包括自身节点) nodesum[ ],一个是其子树各点到它的期望时间和 dp[ ]。那么我们假设根节点为 u ,其仅有一个儿子 v , u 到 v 的距离为 w ,而 v 有若干儿子节点,那么 dp[v] 表示 v 的子树各点到 v 的期望时间和,那么各个节点到达 u 的期望时间和便可以这样计算: dp[u] = dp[v] + nodesum[ v ] *w; (式子的理解,v 的一个儿子节点为 f,那么 f 到达 u 的期望时间为 (sum[ f ->v] + sum [v- > u])*val[f] (其中 val[v] 为 f 的权值),dp[v] 包含了 sum[f->v]*val[f],所以也就是式子的分配式推广到各个子节点计算出来的和),求出了 nodesum[ ] 数组和 dp[ ] 数组后,对于 q 个询问可以快速的求出。我们已经知道了各个节点到达根节点的期望时间和,那么从根节点开始递推下来可以得到各个点的期望时间和。另开一个数组表示每个节点的期望时间和,那么 dissum[u] = dp[u]。以 u 的儿子 v 为例, v 的子节点到 v 不必经过 v->u 这条路径,因此 dissum[u] 多了 nodesum[v] * w,但是对于不是 v 的子节点的节点,只到达了 u ,因此要到达 v 必须多走 u->v 这条路径,因此 dissum[u] 少了 ( totaval - nodesum[v] ) * w) ,所以 dissum[v] = dissum[u] - nodesum[v] * w + (total - nodesum[v] ) * w,按照这个方法递推下去就可以得到各个点的期望时间和。
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- using namespace std;
- const int maxn = 100005;
- struct Edge{
- int u,v,w,next;
- }edge[maxn<<1];
- int tot = 0,totval= 0,head[maxn],val[maxn],nodesum[maxn],dissum[maxn],dp[maxn];
- void addedge(int u,int v,int w)
- {
- edge[tot].u = u,edge[tot].v = v,edge[tot].w = w,edge[tot].next = head[u];
- head[u] = tot++;
- }
- void dfs1(int u,int fa)
- {
- int i;
- dp[u] = 0,nodesum[u] = val[u];
- for (i = head[u];~i;i = edge[i].next)
- {
- int v = edge[i].v,w = edge[i].w;
- if (v == fa) continue;
- dfs1(v,u);
- dp[u] += dp[v] + nodesum[v]*w;
- nodesum[u] += nodesum[v];
- }
- }
- void dfs2(int u,int fa)
- {
- int i;
- for (i = head[u];~i;i = edge[i].next)
- {
- int v = edge[i].v,w = edge[i].w;
- if (v == fa) continue;
- dissum[v] = dissum[u] - nodesum[v]*w + (totval - nodesum[v])*w;
- dfs2(v,u);
- }
- }
- int main()
- {
- //freopen("input.txt","r",stdin);
- int N,i,u,v,w,m,tmp;
- memset(head,-1,sizeof(head));
- scanf("%d",&N);
- for (i = 1;i <= N;i++) scanf("%d",&val[i]),totval += val[i];
- for (i = 1;i < N;i++)
- {
- scanf("%d%d%d",&u,&v,&w);
- addedge(u,v,w);
- addedge(v,u,w);
- }
- dfs1(1,1);
- dissum[1] = dp[1];
- dfs2(1,1);
- scanf("%d",&m);
- for (i = 1;i <= m;i++)
- {
- scanf("%d",&tmp);
- printf("%d\n",dissum[tmp]);
- }
- return 0;
- }
数据结构作业——expectation(树形dp+dfs)的更多相关文章
- HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca
Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- poj 3140 Contestants Division(树形dp? dfs计数+枚举)
本文出自 http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...
- 树的直径的求法即相关证明【树形DP || DFS】
学习大佬:树的直径求法及证明 树的直径 定义: 一棵树的直径就是这棵树上存在的最长路径. 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之间的距 ...
- 刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)
题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There ar ...
- VIJOS1476 旅行规划(树形Dp + DFS暴力乱搞)
题意: 给出一个树,树上每一条边的边权为 1,求树上所有最长链的点集并. 细节: 可能存在多条最长链!最长链!最长链!重要的事情说三遍 分析: 方法round 1:暴力乱搞Q A Q,边权为正-> ...
- [USACO10MAR]伟大的奶牛聚集 BZOJ 1827 树形dp+dfs
题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, of cours ...
- BZOJ4784 ZJOI2017仙人掌(树形dp+dfs树)
首先考虑是棵树的话怎么做.可以发现相当于在树上选择一些长度>=2的路径使其没有交,同时也就相当于用一些没有交的路径覆盖整棵树. 那么设f[i]为覆盖i子树的方案数.转移时考虑包含根的路径.注意到 ...
随机推荐
- 你知道JavaScript中的结果值是什么吗?
你知道JavaScript中的每条语句.甚至表达式都有一个结果值吗? 当你在浏览器中测试代码时,经常会在控制台的输出结果的最后面多出一条,大部分为undefined,这个undefined就是一个结果 ...
- SharePoint2016母版页的直接依赖项的数目限制超过10的限制解决方案Direct Dependencies Limit with Master page User Controls
前言 最近母版制作站点模板,根据站点模板新建后发现如下错误: 解决方案 1. 打开C:\inetpub\wwwroot\wss\VirtualDirectories\,如下图: 2. 打开web.co ...
- UITextField
UITextFieldDemo 效果 特点 1.有效定制键盘的样式 2.处理键盘对文本框的遮挡 用法 1.导入文件(UITextField+CreateInputAccessoryView.h/.m) ...
- 自定义UITabBarController标签视图控制器
首先创建一个类,继承自UItabBarController 然后在.m文件中: 这里我有两个宏定义: #define WIDTH (myView.frame.size.width / 4) //我在写 ...
- 使用PullToRefresh插件实现ListView下拉刷新(Android Studio)
下载PullToRefresh
- Extjs5 tree扩展----treepanel树组件
Ext.define('MyExtend.lib.TreeFilter', { filterByText: function(text) { this.f ...
- MS SQL巡检系列——检查重复索引
前言感想:一时兴起,突然想写一个关于MS SQL的巡检系列方面的文章,因为我觉得这方面的知识分享是有价值,也是非常有意义的.一方面,很多经验不足的人,对于巡检有点茫然,不知道要从哪些方面巡检,另外一方 ...
- Oracle数据库11g各版本介绍及功能比较
.标准版和企 业版.所有这些版本都使用相同的通用代码库构建,这意味着企业的数据库管理软件可以轻松地从规模较小的单一处理器服务器扩展到多处理器服务器集 群,而无需更改一行代码.Oracle数据库11g企 ...
- Linux 系统中的MySQL数据库默认区分大小写
今天在开发中遇到这么个问题,将连接的数据库改为服务器上的时候(服务器是Linux系统的),程序跑起来后一直出错,总提示数据库的表找不到, 而打开数据库看该表明明是存在的,在我的印象中MySQL数据是不 ...
- ubuntu下修改键位
尴尬的背景: 服役5年的笔记本,最近键盘失灵,部分键位彻底失去响应.最蛋疼的是左右方向键都不能用了 ○| ̄|_ 解决方案是,通过xmodmap命令,用其他相对鸡肋些的键位替代方向键. 1 查看各个键位 ...