POJ 1741Tree 树的分治
来源:互联网 发布:淘宝双11销量排名 编辑:程序博客网 时间:2024/05/20 12:47
题目:http://poj.org/problem?id=1741
题意:给定一棵树,有n个点和n - 1条边,边有边权,给出一个K,求树上任意两点间的最短距离不大于K的个数
思路:看了09年漆子超的论文,利用分治法,每次找树的重心,重心即是在当前树中删掉此点后,节点数最多的子树的节点数最小,找到重心后,求其所有子孙到其的距离,然后统计一下两两之和不大于K的个数,另外在统计过程中,会把在同一分支中的两点也计算了,即这两点间的路径不经过重心,这明显是多余的,所以要减掉
总结:树上的算法真是巧妙啊。。。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 10010;struct edge{ int to, val, next;}g[N*2];int head[N], siz[N], sonsiz[N], dis[N];bool vis[N];int n, k, root, res, tmp, num, cnt;void add_edge(int v, int u, int val){ g[cnt].to = u; g[cnt].val = val; g[cnt].next = head[v]; head[v] = cnt++;}void dfssiz(int v, int fa) /*处理以v点为根的树的节点个数和v的子树中节点最多的子树节点数*/{ siz[v] = 1, sonsiz[v] = 0; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(u != fa && ! vis[u]) { dfssiz(u, v); siz[v] += siz[u]; sonsiz[v] = max(sonsiz[v], siz[u]); } }}void dfsroot(int r, int v, int fa) /*寻找重心*/{ sonsiz[v] = max(sonsiz[v], siz[r] - siz[v]); /*以v为重心时,节点最多的子树节点数*/ if(sonsiz[v] < tmp) tmp = sonsiz[v], root = v; /*更新重心*/ for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(u != fa && ! vis[u]) dfsroot(r, u, v); }}void dfsdis(int v, int d, int fa) /*计算重心到每个子孙的距离*/{ dis[num++] = d; for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(u != fa && ! vis[u]) dfsdis(u, d + g[i].val, v); }}int calc(int v, int d){ int ans = 0; num = 0; dfsdis(v, d, 0); sort(dis, dis + num); int i = 0, j = num - 1; while(i < j) /*计算两点距离小于k的个数,很巧妙*/ { while(dis[i] + dis[j] > k && i < j) j--; ans += j - i; i++; } return ans;}void dfs(int v){ tmp = n; dfssiz(v, 0); dfsroot(v, v, 0); res += calc(root, 0); vis[root] = true; /*标记重心,拆掉*/ for(int i = head[root]; i != -1; i = g[i].next) { int u = g[i].to; if(! vis[u]) { res -= calc(u, g[i].val); /*多算了在同一分支上的两点,因此减去*/ dfs(u); } }}int main(){ int a, b, c; while(scanf("%d%d", &n, &k), n || k) { cnt = res = 0; memset(head, -1, sizeof head); memset(vis, 0, sizeof vis); for(int i = 0; i < n - 1; i++) { scanf("%d%d%d", &a, &b, &c); add_edge(a, b, c); add_edge(b, a, c); } dfs(1); printf("%d\n", res); } return 0;}
0 0
- POJ 1741 Tree 树的分治
- poj 1741 Tree 树的分治
- poj 1741 Tree(树的分治)
- POJ 1741 Tree 树的点分治
- poj 1741 Tree 树的分治
- poj 1741 Tree 树的分治
- POJ - 1741 Tree 树的分治
- POJ 1741Tree 树的分治
- [POJ 1741] Tree (树的分治)
- poj 1741 Tree(树的分治)
- Poj-1741 Tree(树的点分治)
- 【poj 1741】tree 树的点分治
- poj 1741 Tree (树的分治)
- POJ 1741 Tree 树的点分治
- poj 1741 Tree 树的点分治
- POJ 1741 Tree 树的点分治
- POJ 1741 Tree, 树的重心, 树分治, 点分治
- POJ 1741 Tree 树的分治(点分治)
- iOS中Info.plist文件的常见配置
- 滑动窗口
- JS跨域问题
- 导致页面打开速度变慢--Session阻塞造成时的解决方案
- mybatis学习目录
- POJ 1741Tree 树的分治
- 彻底明白Android中AIDL及其使用
- org.apache.log4j.PatternLayout的输出格式
- AFNetworking 3.0 Code=-1016 错误解决方案
- 格式化数字,保存指定的小数位置NumberFormat类
- mysql远程连接
- java读写excel(POI,支持xls和xlsx两种格式)
- 算法小结--二分搜索
- 高效快捷简便易用的基于JSP的开源框架 MVC+ORM框架- YangMVC