HDU 2376 树形dp|树上任意两点距离和的平均值
2016-07-22 15:15
302 查看
原题:http://acm.hdu.edu.cn/showproblem.php?pid=2376
经典问题,求的是树上任意两点和的平均值。
这里我们不能枚举点,这样n^2的复杂度。我们可以枚举每一条边,设这条边的端点分别为A、B,则通过这条边的路径总数为与A点相连的端点数乘以与B点相连的端点数,再乘以这条边的权值,将所有的和相加,最后除以n*(n-1)/2就可以了(除以2是因为这里每条边重复计算了两次)。
这里统计求和的时候,一遍深搜就可以了,需要注意的是,假设某个点子树所包含点的个数为k,则这条边另一个端点所包含的点的个数的为n-k。
经典问题,求的是树上任意两点和的平均值。
这里我们不能枚举点,这样n^2的复杂度。我们可以枚举每一条边,设这条边的端点分别为A、B,则通过这条边的路径总数为与A点相连的端点数乘以与B点相连的端点数,再乘以这条边的权值,将所有的和相加,最后除以n*(n-1)/2就可以了(除以2是因为这里每条边重复计算了两次)。
这里统计求和的时候,一遍深搜就可以了,需要注意的是,假设某个点子树所包含点的个数为k,则这条边另一个端点所包含的点的个数的为n-k。
#include<bits/stdc++.h> using namespace std; const int maxn = 11111; struct node{ int v;//终点 int w;//权值 }; vector<node> tree[maxn]; long long dp[maxn]; int sum[maxn];//统计每个点子树所包含点的个数 int n; void dfs(int cur,int father){ sum[cur] = 1; for(int i = 0;i<tree[cur].size();i++){ int son = tree[cur][i].v; long long len = tree[cur][i].w; if(father == son) continue; dfs(son,cur); sum[cur] += sum[son]; dp[cur] += dp[son]+sum[son]*(n-sum[son])*len; } } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i = 0;i<n;i++) tree[i].clear(); memset(dp,0,sizeof(dp)); memset(sum,0,sizeof(sum)); int u,v,w; for(int i = 0;i<n-1;i++){ scanf("%d%d%d",&u,&v,&w); node t1,t2; t1.v = v; t1.w = w; t2.v = u; t2.w = w; tree[u].push_back(t1); tree[v].push_back(t2); } //以任意一点为根进行搜索 dfs(0,-1); printf("%lf\n",dp[0]*2.0/n/(n-1)); } return 0; }
相关文章推荐
- JS - 柯里化
- Lambda 表达式
- http--状态码
- LeetCode-难题集之Best_Time_to_Buy_and_Sell_Stock系列
- 几种任务调度的 Java 实现方法与比较
- Linux系统中安装VMware Tool
- JSONObject和XML和java等之间的转换
- SICP 习题2.60 允许元素重复,重构集合操作
- 菜单中英文切换
- 【转载】小tips: PC端传统网页试试使用Zepto.js进行开发
- flash上传图片的问题
- java基础——用HttpURLConnection向服务器发送POST请求
- 《Java源码分析》:Stack
- java基础:位运算的魅力
- React移动web极致优化
- iOS 开发 - iOS 8 以后使用UIAlertController的使用
- mariadb用户和权限管理
- PHPCMS_V9 模型字段添加单文件上传功能
- UIcollectionView的使用(首页的搭建1)
- offsetTop与offset().top