Link:

POJ 1741 传送门

Solution:

此题的难点在于点分治上的统计

如果依然采取每棵子树的结果与之前所有子树的结果合并的方式会比较麻烦

同时复杂度可能超过$O(n*log(n))$的限制

其实可以用一个简单的容斥来在$O(n*log(n))$统计结果:

先将所有点到重心的距离排序,维护左右指针来直接统计结果

但这样明显会重复计算两个点在同一棵子树中的情况,按照同样的操作将其除去即可

Code:

//by NewErA
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>using namespace std;
typedef pair<int,int> P;const int MAXN=10005;
vector<P> G[MAXN];vector<int> tmp;
int n,k,mx_sub[MAXN],sz[MAXN],vis[MAXN],v_sum=0,root,res=0;
int dist[MAXN];void getroot(int x,int anc)
{sz[x]=1;mx_sub[x]=0;for(int i=0;i<G[x].size();i++){int v=G[x][i].first;if(v==anc || vis[v]) continue;getroot(v,x);sz[x]+=sz[v];mx_sub[x]=max(mx_sub[x],sz[v]);}mx_sub[x]=max(mx_sub[x],v_sum-sz[x]);if(mx_sub[x]<mx_sub[root]) root=x;
}void cal_dep(int x,int anc)
{tmp.push_back(dist[x]);for(int i=0;i<G[x].size();i++){int v=G[x][i].first;if(v==anc || vis[v]) continue;dist[v]=dist[x]+G[x][i].second;cal_dep(v,x);}
}int cal(int x,int start_point)
{tmp.clear();dist[x]=start_point;cal_dep(x,0);sort(tmp.begin(),tmp.end());int ret=0,l=0,r=tmp.size()-1;while(l<r){if(tmp[l]+tmp[r]<=k)ret+=(r-l),l++;else r--;}return ret;
}void solve(int x)
{res+=cal(x,0);vis[x]=true;for(int i=0;i<G[x].size();i++){int v=G[x][i].first;if(vis[v]) continue;res-=cal(v,G[x][i].second);v_sum=sz[v];getroot(v,root=0);solve(root);}
}int main()
{while(scanf("%d%d",&n,&k)!=EOF && n && k){for(int i=0;i<=n;i++) G[i].clear(),vis[i]=mx_sub[i]=0;for(int i=1;i<n;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);G[x].push_back(P(y,z));G[y].push_back(P(x,z));}mx_sub[0]=v_sum=n;getroot(1,root=0);res=0;solve(root);printf("%d\n",res);}return 0;
}

Review:

点分治中可用容斥的思想来统计

先计算任意两点的结果,再减去两点在同一棵子树中的结果(重心转移后会重复计算)

转载于:https://www.cnblogs.com/newera/p/9303056.html

[POJ 1741] Tree相关推荐

  1. POJ 1741 Tree(树的点分治)

    题目链接:http://poj.org/problem?id=1741 题意:给出一棵树,定义dis(u,v)为两个节点之间的距离.dis(u,v)<=K时成(u,v)是合法的.问有多少个合法的 ...

  2. poj 1741 Tree

    点分治裸题23333这个题如果K很大的话就不能用依次处理每棵子树做了.(数组存不开2333) 这个就只能是总的依次减去每棵子树里的. 1 #include<cstdio> 2 #inclu ...

  3. POJ 1741 Tree(树分治)

    去网上搜题解大多数都是说论文,搜了论文看了看,写的确实挺好,直接复制过来. 不过代码中有些细节还是要注意的,参考这篇http://blog.sina.com.cn/s/blog_6d5aa19a010 ...

  4. POJ 1741 Tree(点分治)

    题意 一棵 \(n\) 个节点的树,求两点间距离不超过 \(k\) 的点对对数. 思路 点分治模板题,点分治一般用来解决树上的路径问题,核心在于找出重心,算经过重心的合法路径,然后以重心把树劈成若干个 ...

  5. POJ - 1741 Tree(点分治模板题)

    题目链接:点击查看 题目大意:给出一棵 n 个节点的树,现在定义 dis( x , y ) 为点 x 和点 y 之间的路径长度,现在问 dis ( x , y ) <= k 的点对有多少 题目分 ...

  6. POJ 1741 Tree 树分治

    题意: 给出一颗有\(n (n \leq 10^4)\)个节点的树,和一个\(k\).统计有多少个点对\(u, \, v(u \neq v)\)满足\(u\)到\(v\)的最短距离不超过\(k\). ...

  7. poj 1145 Tree Summing

    // poj 1145 Tree Summing /* 交了好多遍才过,注意几点: 1.输入可能有负数:2.叶子节点判断要准确,是两个子节点都没有的节点:3.空树答案为no */ #include & ...

  8. 【POJ - 1741】Tree(树分治,容斥,点分治,模板题)

    题干: Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist ...

  9. POJ 1741 树分治

    题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...

最新文章

  1. 悬浮按钮app_分享一款网页转App的神器,绝对值得一用
  2. 修改react-native项目名称
  3. xgboost 正则项_深入理解Boosting算法(4)-XGBoost
  4. Java进阶:CountDownLatch倒计时
  5. 从mysqldump整库备份文件中恢复单表
  6. pandas - Series
  7. php strstr 效率,PHP中的stristr(),strstr(),strpos()速度比较
  8. Android监听事件
  9. 新年发财专属红包封面,高端大气上档次!
  10. PAC自动代理文件格式,教你如何写PAC文件
  11. whitelist方法_Jsoup学习之Whitelist类
  12. 在linux安装docker以及docker的常用命令(一)
  13. 如何在 Safari 下载 ZIP 文件后不自动解压?
  14. springboot整合rabbitmq之延时队列
  15. 从0开始学习C#第二天
  16. dosbox中out of memory_flink教程-详解flink 1.11 中的JDBC Catalog
  17. linux三种用户界面,Linux的图形用户界面-你会选择哪个?
  18. 根本原因分析(RCA)
  19. 沪牌学院-沪拍拍课堂1: 估价策略
  20. GPU、CPU、显卡区别

热门文章

  1. linux系统reboot怎么退出,Linux系统肿么退出?
  2. 行业短信 运营思路_飞信、易信之后 三大运营商要借5G再战微信
  3. python遍历文件夹下所有文件大小_python遍历文件夹读取文件大小 | 学步园
  4. 安装linux办公软件,Centos7如何安装开源办公软件Libreoffice
  5. 点击鼠标左键 自动锁定计算机图标,鼠标一按左键桌面图标就消失了怎么办_为什么按鼠标左键时桌面图标都不见了...
  6. 虚拟机出现蓝屏解决方法
  7. picACG本地缓存目录_7天用Go动手写/从零实现分布式缓存GeeCache
  8. [JUC-5]ConcurrentHashMap源码分析JDK8
  9. Firefox 将导入 Windows 根证书,避免与杀毒软件的冲突
  10. 程序清单3.3_bases.c程序_《C Primer Plus》P37