Tree

P4178 Tree

点分治板子。

点分治就是直接找树的重心进行暴力计算,每次树的深度不会超过子树深度的\(\frac{1}{2}\),计算完就消除影响,找下一个重心。

所以伪代码:

void solve(int u)
{
calc(u);
used[u]=true;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(!used[v])
{
getroot(v)
solve(root);
}
}
}

calc因题而异,主要靠思维。

这两题仅数据范围不同,这里放POJ的代码。

用个值域树状数组可以快速计算出距离不超过一个数的路径个数。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=40010;
const int inf=10000007;
struct edge {
int to,nxt,val;
} e[N<<1];
int head[N],num_edge,rt,k,ans,a[N],b[N],d[N],mn,t[inf],n;
bool used[N];
int max(const int &a,const int &b){return a>b?a:b;}
inline void add(int from,int to,int val) {
++num_edge;
e[num_edge].nxt=head[from];
e[num_edge].val=val;
e[num_edge].to=to;
head[from]=num_edge;
}
#define lt(x) (x&(-x))
void add(int i,int x) {
if(i<=0)return;
while(i<=k) {
t[i]+=x;
i+=lt(i);
}
}
int ask(int i) {
if(i<=0)return 0;
int res=0;
if(i>k)i=k;
while(i) {
res+=t[i];
i-=lt(i);
}
return res;
}
int mx[N],size[N],sum;
void getrt(int u,int fa)
{
mx[u]=0,size[u]=1;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa||used[v])continue;
getrt(v,u);
size[u]+=size[v];
mx[u]=max(mx[u],size[v]);
}
mx[u]=max(sum-mx[u],mx[u]);
if(mx[u]<mx[rt])rt=u;
}
void getdis(int u,int fa,int dis) {
if(dis>k)return;
a[++a[0]]=dis;b[++b[0]]=dis;
for(int i=head[u]; i; i=e[i].nxt) {
int v=e[i].to;
if(v==fa||used[v])continue;
getdis(v,u,dis+e[i].val);
}
}
void calc(int u) {
b[0]=0;
for(int i=head[u]; i; i=e[i].nxt) {
int v=e[i].to;
if(used[v])continue;
a[0]=0;getdis(v,u,e[i].val);
for(int j=1; j<=a[0]; ++j) {
if(a[j]>k)continue;
ans+=ask(k-a[j]);
}
for(int j=1; j<=a[0]; ++j) {
if(a[j]>k)continue;
add(a[j],1);
++ans;
}
}
for(int i=1; i<=b[0]; ++i) {
if(b[i]>k)continue;
add(b[i],-1);
}
}
void solve(int u) {
used[u]=true,calc(u);
for(int i=head[u]; i; i=e[i].nxt) {
int v=e[i].to;
if(!used[v])
{
rt=0;
sum=size[v];
getrt(v,u);
solve(rt);
}
}
}
void clear()
{
num_edge=0;ans=0;
memset(head,0,sizeof(head));
memset(used,false,sizeof(used));
}
int main() {
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==0&&k==0)return 0;
clear();
for(int i=1,x,y,z; i<n; ++i) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
sum=mx[rt=0]=n;
getrt(1,0);
solve(rt);
printf("%d\n",ans);
}
}

POJ1471 Tree/洛谷P4178 Tree的更多相关文章

  1. 点分治模板(洛谷P4178 Tree)(树分治,树的重心,容斥原理)

    推荐YCB的总结 推荐你谷ysn等巨佬的详细题解 大致流程-- dfs求出当前树的重心 对当前树内经过重心的路径统计答案(一条路径由两条由重心到其它点的子路径合并而成) 容斥减去不合法情况(两条子路径 ...

  2. 洛谷P4178 Tree (点分治)

    题目描述 给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K 输入输出格式 输入格式:   N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下 ...

  3. 洛谷 P4178 Tree —— 点分治

    题目:https://www.luogu.org/problemnew/show/P4178 这道题要把 dep( dis? ) 加入一个 tmp 数组里,排序,计算点对,复杂度很美: 没有写 sor ...

  4. 洛谷P4178 Tree (算竞进阶习题)

    点分治 还是一道点分治,和前面那道题不同的是求所有距离小于等于k的点对. 如果只是等于k,我们可以把重心的每个子树分开处理,统计之后再合并,这样可以避免答案重复(也就是再同一个子树中出现路径之和为k的 ...

  5. 2018.07.20 洛谷P4178 Tree(点分治)

    传送门 又一道点分治. 直接维护子树内到根的所有路径长度,然后排序+双指针统计答案. 代码如下: #include<bits/stdc++.h> #define N 40005 using ...

  6. [洛谷P4178]Tree

    题目大意:给一棵树,问有多少条路径长度小于等于$k$ 题解:点分治 卡点:无 C++ Code: #include <cstdio> #include <algorithm> ...

  7. 洛谷 P4178 Tree

    #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #inclu ...

  8. [洛谷P4178] Tree (点分治模板)

    题目略了吧,就是一棵树上有多少个点对之间的距离 \(\leq k\) \(n \leq 40000\) 算法 首先有一个 \(O(n^2)\) 的做法,枚举每一个点为起点,\(dfs\) 一遍可知其它 ...

  9. POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量

    POJ 1741. Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 34141   Accepted: 11420 ...

随机推荐

  1. 【Python矩阵及其基础操作】【numpy matrix】

    一.矩阵生成 1.numpy.matrix: import numpy as np x = np.matrix([ [1, 2, 3],[4, 5, 6] ]) y = np.matrix( [1, ...

  2. 「快学springboot」SpringBoot多环境配置文件

    前言 我们都知道springboot的配置卸载application.properties配置文件上(或者application.yml).但是,如果想要把不同的环境(如开发环境,测试环境,生产环境) ...

  3. 查找字符串strscan

    ;Author : Bing ;Date : 1/10/2019;Usage: modify log drictory according to actual drictory fileopen fh ...

  4. MySQL之关系

    目录 关系 多对多的关系,如何通过mysql来表示 一对一关系 关系 多对多的关系,如何通过mysql来表示 站在老师的角度 一个老师可以教多个学生, 一个老师也可以教一个学生. 站在学生的角度 一个 ...

  5. spring boot 中的配置文件可以存放的位置

  6. minst.npz下载

    keras.datasets.mnist数据集下载地址 下载地址:链接: https://pan.baidu.com/s/1Rr-aHsIIEQx2z6W3qvMmhQ 提取码: 8w15

  7. ProgressBarForm 进度条

    ProgressBarForm public partial class ProgressBarForm : Form { private Panel panel1 = new System.Wind ...

  8. android悬浮按钮(Floating action button)的两种实现方法

    原文: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1028/1857.html 最近android中有很多新的设计规范被引入 ...

  9. 自定义Toast排队重复显示问题:

    原文 http://blog.csdn.net/baiyuliang2013/article/details/38655495Toast是安卓系统中,用户误操作时或某功能执行完毕时,对用户的一种提示, ...

  10. Python 基础之循环结构for及break pass continue

    一.for 循环 #循环 变量 迭代 都是一个意思#把列表里面的元素意义的拿出来就是遍历listvar = ["one","two","three&q ...