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. Maven的安装与配置(eclipse,idea)

    Maven的安装与配置   一.需要准备的东西 1. JDK 2. Maven程序包 3. Eclipse 4. Idea 二.下载与安装 1. 前往https://maven.apache.org/ ...

  2. SpringBoot 集成JUnit

    项目太大,不好直接测整个项目,一般都是切割成多个单元,单独测试,即单元测试. 直接在原项目上测试,会把项目改得乱七八糟的,一般是单独写测试代码. 进行单元测试,这就需要集成JUnit. (1)在pom ...

  3. 学习之学习--混沌大学商学院--第一课--HHR计划

    <学习之学习> 第一课:混沌初开 李善友 1,课程目标:建立个人的多元思维模型,帮助企业找到创新驱动的增长战略. 2,创新:第二曲线创新,创新理论之父熊彼特. 3,核心课:第二曲线,非连续 ...

  4. CentOS7配置python3教程

    环境准备: 1.python3.7.1 下载地址:https://www.python.org/    注意:CentOS7默认就有python2的 2.虚拟机CentOS 7 64位,下载地址:ht ...

  5. 【python-leetcode25-翻转链表】K 个一组翻转链表

    问题描述: 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序. 示例 ...

  6. 【转】Docker学习_本地/容器文件互传(5)

    将容器内文件拷贝到宿主机 docker cp <containerId>:/导出文件的位置/xxx.sql /宿主机的位置 示例:docker cp bf4c4fff338c:/root/ ...

  7. Thymeleaf的内置属性(转)

    原文链接: http://somefuture.iteye.com/blog/2253761 Thymeleaf是另一个Java视图模板引擎,使用上和FreeMarker各有千秋,不了解的可以从其他博 ...

  8. 列表推导式、生成器表达式以及zip()max()max()/min()sum()sort()map()filter()的用法

    列表推导式: 基本格式: variable = [out_exp_res for out_exp in input_list if out_exp == 2] #out_exp_res: 列表生成元素 ...

  9. 「Violet」蒲公英

    「Violet」蒲公英 传送门 区间众数,强制在线. 分块经典题. 像这题一样预处理,然后就直接爆搞,复杂度 \(O(n \sqrt n)\) 参考代码: #include <algorithm ...

  10. “嘭、嘭、嘭”---C/S架构下的心跳机制

    本人想使用AU3开发多客户端.一服务端.需要使用到心跳机制,即 在线状态实时更新以及掉线自动重连. 搜索网络发现没有人用AU3写心跳机制. 下面是一篇转帖(原文地址:http://www.cnblog ...