【日常学习】【树形DP】codevs3023 魔法禁书目录1:追捕大妈题解
2015-09-12 16:26
295 查看
题目描述 Description
index饿了,她要找大妈做饭,可是大妈早在错综复杂的学院都市的一处跟炮姐(jq),学院都市是个无向连通图,游走状态的index想要知道对于所有当麻可能在的地点和自己每个游走的地点,平均距离是多少
一句话题意
给定一个含n个点的无向连通图,任意两点间有且仅有一条路径,求两点间距离的平均值,即 ∑disij/(n*n-n) (1≤i≤n,1≤j≤n)
输入描述 Input Description
第一行一个正整数n
随后n-1行每行3个正整数a b c,表示a b两点间有一条长度为c的边
输出描述 Output Description
输出两点间平均距离,保留两位小数。
样例输入 Sample Input
4
1 2 1
2 3 1
2 4 1
样例输出 Sample Output
1.50
数据范围及提示 Data Size & Hint
40%数据中n≤200
60%数据中n≤2000
100%数据中n≤20000
边的长度≤10000
这是我们组内互测时TY君给的题目 我的代码总之是怎么样都过不了的 搜索过程我放在注释里了 哪位神仙能看明白的话烦请不吝指教 鄙人实在蒟蒻···
题目大意如下
树上有n个节点(n<=两万) 给你任意两点间距离 输出平均距离
直接枚举肯定超时,一个好的思路是:
边两端的点数分别为A和B,这条边被经过的次数就是A*B,
它对总的距离和的贡献就是(A*B*此边长度)
求和再除以总路径数N*(N-1)/2
那么就是求每条边两端点的个数 计算一次dfs解决
任取一点为根,在dfs的过程中,对每个点k记录其子树包含的点数(包括其自身)
设点数为a[k],则k的父亲一侧的点数即为N-a[k] 注意乘的时候应该改一改
统计和遍历同时进行 故时间复杂度为O(n)
但是我想我应该是在DFS和最后对边的处理出问题了 TY君的数据都过了 但是codevsA3W7 于是参照着TY君的代码改了一下 最终A了
我们不同之处在于,TY写的显然是树形DP这样子的,一边DFS一边处理 而我是最后扫一遍边集中处理 另外TY君的搜索父子关系很分明,而我用visit数组检验是否为父亲的方法显然要拙劣很多
先把我的代码放上吧:
接下来贴上TY的,很简短,用vector存图···虽然我并没有看懂,但是结构体中构造器的运用是很好的
这次比赛真是惨不忍睹,如果这是NOIP我们可怎么办才好,四百分的题目我才60分
想想第一题,应该算是算法不对 第二题正解是DP 第三题是递推高精 这两道题都没想到 然而至少写个搜索还能得点分数 第三题没想到的原因主要是看题之后没能理清思路找规律吧 第四题 应该说我搜索的思路还是不清晰,没有算法的完整框架,没有想到这是一个树形DP 因此即使算法正确 实现起来问题还是很大 细节处理上也还是漏洞很多 而且代码能力还需要进一步提高
所以还是要加油啊···
——纸上得来终觉浅,绝知此事要躬行
index饿了,她要找大妈做饭,可是大妈早在错综复杂的学院都市的一处跟炮姐(jq),学院都市是个无向连通图,游走状态的index想要知道对于所有当麻可能在的地点和自己每个游走的地点,平均距离是多少
一句话题意
给定一个含n个点的无向连通图,任意两点间有且仅有一条路径,求两点间距离的平均值,即 ∑disij/(n*n-n) (1≤i≤n,1≤j≤n)
输入描述 Input Description
第一行一个正整数n
随后n-1行每行3个正整数a b c,表示a b两点间有一条长度为c的边
输出描述 Output Description
输出两点间平均距离,保留两位小数。
样例输入 Sample Input
4
1 2 1
2 3 1
2 4 1
样例输出 Sample Output
1.50
数据范围及提示 Data Size & Hint
40%数据中n≤200
60%数据中n≤2000
100%数据中n≤20000
边的长度≤10000
这是我们组内互测时TY君给的题目 我的代码总之是怎么样都过不了的 搜索过程我放在注释里了 哪位神仙能看明白的话烦请不吝指教 鄙人实在蒟蒻···
题目大意如下
树上有n个节点(n<=两万) 给你任意两点间距离 输出平均距离
直接枚举肯定超时,一个好的思路是:
边两端的点数分别为A和B,这条边被经过的次数就是A*B,
它对总的距离和的贡献就是(A*B*此边长度)
求和再除以总路径数N*(N-1)/2
那么就是求每条边两端点的个数 计算一次dfs解决
任取一点为根,在dfs的过程中,对每个点k记录其子树包含的点数(包括其自身)
设点数为a[k],则k的父亲一侧的点数即为N-a[k] 注意乘的时候应该改一改
统计和遍历同时进行 故时间复杂度为O(n)
但是我想我应该是在DFS和最后对边的处理出问题了 TY君的数据都过了 但是codevsA3W7 于是参照着TY君的代码改了一下 最终A了
我们不同之处在于,TY写的显然是树形DP这样子的,一边DFS一边处理 而我是最后扫一遍边集中处理 另外TY君的搜索父子关系很分明,而我用visit数组检验是否为父亲的方法显然要拙劣很多
先把我的代码放上吧:
接下来贴上TY的,很简短,用vector存图···虽然我并没有看懂,但是结构体中构造器的运用是很好的
#include<bits/stdc++.h> using namespace std; struct edge{ int from,to,dis; edge(){}; edge(int x,int y,int z){ from=x,to=y,dis=z; } }; vector<edge>es; vector<int>G[20005]; int size[20005]; double dp[20005]; int cnt,n; void add(int u,int v,int w){ es.push_back(edge(u,v,w)); G[u].push_back(es.size()-1); } void dfs(int u,int f=0){ size[u]=1; for(int i=0;i<G[u].size();++i){ edge& x=es[G[u][i]]; if(x.to==f)continue; dfs(x.to,u); size[u]+=size[x.to]; dp[u]+=dp[x.to]+size[x.to]*(n-size[x.to])*(double)x.dis; } } int main(){ freopen("D.in","r",stdin); freopen("D.out","w",stdout); scanf("%d",&n); for(int i=1,a,b,c;i<n;++i){ scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } dfs(1); int s=(n*n-n)/2; printf("%.2lf\n",(double)dp[1]/s); }
这次比赛真是惨不忍睹,如果这是NOIP我们可怎么办才好,四百分的题目我才60分
想想第一题,应该算是算法不对 第二题正解是DP 第三题是递推高精 这两道题都没想到 然而至少写个搜索还能得点分数 第三题没想到的原因主要是看题之后没能理清思路找规律吧 第四题 应该说我搜索的思路还是不清晰,没有算法的完整框架,没有想到这是一个树形DP 因此即使算法正确 实现起来问题还是很大 细节处理上也还是漏洞很多 而且代码能力还需要进一步提高
所以还是要加油啊···
——纸上得来终觉浅,绝知此事要躬行
相关文章推荐
- “数据结构基础”系列网络课程主页
- Linux和Windows的换行符
- 深入理解Spring Redis的使用 (九)、通过Redis 实现 分布式锁 的 BUG,以及和数据库加锁的性能测试
- centos7.x 防火墙配置:关闭firewall 安装iptables
- python 内置函数filter和sorted的使用
- jeecms自定义标签
- 继承和多态的代码示例
- 找到两个不相容子数组的最大和
- Unity5 新功能解析--GI(全局光)
- Populating Next Right Pointers in Each Node
- 《剑指offer》二叉树的深度
- URL tailing slash
- 【剑指offer】二十、字符串的排列
- 【转】获取/设置IFRAME内对象元素的几种JS方法
- 隔月生兔子 斐波纳契数列
- [Phonegap+Sencha Touch] 移动开发5、Sencha touch结合Phonegap使用
- 不要只因一次挫败,就放弃你原来决心想达到的梦想
- ACM 数塔/dp入门
- Baskets of Gold Coins Time Limit: 1000/1000 MS (Java/Others) Memory Lim
- 使用Camera与SurfaceView实现自定义拍照功能