P4178 Tree(点分治)
题面要求小于等于K的路径数目,我么很自然的想到点分治(不会的就戳我)
这道题的统计答案与模板题不一样的地方是由等于K到小于等于K
那么我们可以把每一个子节点到当前根(重心)的距离排序,然后用类似双指针的方法来求小于等于K的边的数量
但是如果只是双指针统计的话,那么以下不合法的情况显然也会被算进答案:

而我们需要的合法路径是长成这样的:

所以我们需要减去上述不合法的路径,怎么减呢?
不难发现,对于所有不合法的路径,都是在当前跟的某一棵子树上的(没有跨越两个子树)
所以我们可以对当前跟节点的每一条边进行遍历,利用容斥的思想减去不合法的路径。
具体操作为:当遍历重心节点的每一个节点时,我们可以重新计算dis,然后把经过了从重心到新遍历的点的边两次的路径剪掉(就是上述不合法路径),最后统计答案即可
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define inf 123456789
il int read()
{
re int x = 0, f = 1; re char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x * f;
}
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define drep(i, s, t) for(re int i = t; i >= s; -- i)
#define Next(i, u) for(re int i = head[u]; i; i = e[i].next)
#define mem(k, p) memset(k, p, sizeof(k))
#define maxn 40005
struct edge{int v, w, next;}e[maxn << 1];
int n, m, head[maxn], cnt, k, ans;
int dp[maxn], vis[maxn], sum, dis[maxn], rt, size[maxn], rev[maxn], tot;
il void add(int u, int v, int w)
{
e[++ cnt] = (edge){v, w, head[u]}, head[u] = cnt;
e[++ cnt] = (edge){u, w, head[v]}, head[v] = cnt;
}
il void getrt(int u, int fr)
{
size[u] = 1, dp[u] = 0;
Next(i, u)
{
int v = e[i].v;
if(v == fr || vis[v]) continue;
getrt(v, u);
size[u] += size[v], dp[u] = max(dp[u], size[v]);
}
dp[u] = max(dp[u], sum - size[u]);
if(dp[u] < dp[rt]) rt = u;
}
il void getdis(int u, int fr)
{
rev[++ tot] = dis[u];
Next(i, u)
{
int v = e[i].v;
if(v == fr || vis[v]) continue;
dis[v] = dis[u] + e[i].w;
getdis(v, u);
}
}
il int doit(int u, int w)
{
tot = 0, dis[u] = w, getdis(u, 0);
sort(rev + 1, rev + tot + 1);
int l = 1, r = tot, ans = 0;
while(l <= r) (rev[l] + rev[r] <= k) ? (ans += r - l, ++ l) : (-- r);
return ans;
}
il void solve(int u)
{
vis[u] = 1, ans += doit(u, 0);
Next(i, u)
{
int v = e[i].v;
if(vis[v]) continue;
ans -= doit(v, e[i].w);
sum = size[v], dp[0] = n, rt = 0;
getrt(v, u), solve(rt);
}
}
int main()
{
n = read();
rep(i, 1, n - 1){int u = read(), v = read(), w = read(); add(u, v, w);}
k = read(), dp[0] = sum = n, getrt(1, 0), solve(rt);
printf("%d", ans);
return 0;
}
P4178 Tree(点分治)的更多相关文章
- 洛谷P4178 Tree (点分治)
题目描述 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K 输入输出格式 输入格式: N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下 ...
- 洛谷 P4178 Tree —— 点分治
题目:https://www.luogu.org/problemnew/show/P4178 这道题要把 dep( dis? ) 加入一个 tmp 数组里,排序,计算点对,复杂度很美: 没有写 sor ...
- P4178 Tree 点分治
思路:点分治 提交:1次 题解: 要求权值和\(\leq K\) 的路径,我们可以类比点分治的模板,把长为\(len\)是否存在,改为\(len\)的路径的条数,并用用树状数组维护前缀和,这样就可以求 ...
- [洛谷P4178] Tree (点分治模板)
题目略了吧,就是一棵树上有多少个点对之间的距离 \(\leq k\) \(n \leq 40000\) 算法 首先有一个 \(O(n^2)\) 的做法,枚举每一个点为起点,\(dfs\) 一遍可知其它 ...
- [Luogu P4178]Tree (点分治+splay)
题面 传送门:https://www.luogu.org/problemnew/show/P4178 Solution 首先,长成这样的题目一定是淀粉质跑不掉了. 考虑到我们不知道K的大小,我们可以开 ...
- POJ1471 Tree/洛谷P4178 Tree
Tree P4178 Tree 点分治板子. 点分治就是直接找树的重心进行暴力计算,每次树的深度不会超过子树深度的\(\frac{1}{2}\),计算完就消除影响,找下一个重心. 所以伪代码: voi ...
- luogu P4178 Tree
题目链接 luogu P4178 Tree 题解 点分治 代码 // luogu-judger-enable-o2 #include<cstdio> #include<algorit ...
- 【题解】[P4178 Tree]
[题解]P4178 Tree 一道点分治模板好题 不知道是不是我见到的题目太少了,为什么这种题目都是暴力开值域的桶QAQ?? 问点对,考虑点分治吧.直接用值域树状数组开下来,统计的时候直接往树状数组里 ...
- 【P4178】Tree——点分治
(题面来自luogu) 题目描述 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K 输入格式 N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 ...
随机推荐
- Tomcat的常用内置对象
Tomcat的常用内置对象 1.request内置对象 所谓内置对象就是容器已经创建好了的对象,如果收到一个用户的请求就会自动创建一个对象来处理客户端发送的一些信息,这个内置对象就是request.类 ...
- wkhtmltox实现网页转换成图片或pdf
1.先下载http://download.gna.org/wkhtmltopdf/obsolete/windows/wkhtmltox-0.11.0_rc1-installer.exe,安装 2.在命 ...
- 1.常用turtle功能函数
#turtle常用命令汇总,括号中的参数仅仅作为举例使用,可根据需要修改 #设置画面背景色 turtle.bgcolor("black") #设置窗口大小和在屏幕上的坐标 turt ...
- QQ音乐vkey获取,更新播放url
QQ音乐接口播放经常换, 最开始 url: `http://ws.stream.qqmusic.qq.com/${musicData.songid}.m4a?fromtag=46` 然后 url:`h ...
- App隐私条款
欢迎光临本app,请您仔细阅读以下条款,如果您对本协议的任何条款表示异议,您可以选择不使用本app:进入本app则意味着您将同意遵守本协议下全部规定,并完全服从于app开发者的统一管理. 第一章 总则 ...
- Java:配置环境(Mac)——JDK
1.下载JDK 官网 打开后,直接下载最新版本. 选择dmg文件下载 2.开始安装,一直下一步. 3.打开终端,查询安装路径:/usr/libexec/java_home,复制备用. 4.配置Java ...
- 随机IP
function rand_ip(){ $ip_longs = array( array('607649792', '608174079'), //36.56.0.0-36.63.255 ...
- #035 大数阶乘 PTA题目6-10 阶乘计算升级版 (20 分)
实际题目 本题要求实现一个打印非负整数阶乘的函数. 函数接口定义: void Print_Factorial ( const int N ); 其中N是用户传入的参数,其值不超过1000.如果N是非负 ...
- 在windows系统下安装linux虚拟机(VMware)
一.下载Vmware安装包(此处我安装的是VMware-workstation-full-14.1.3) 链接: https://pan.baidu.com/s/12xT1JaA7eheEgFfM-2 ...
- python selenium while 循环
while True: try: loadmore = browser.find_element_by_xpath('//div[@class="right"]/div[@clas ...