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

Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001). 
Define dist(u,v)=The min distance between node u and v. 
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k. 
Write a program that will count how many pairs which are valid for a given tree. 

Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l. 
The last test case is followed by two zeros. 

Output

For each test case output the answer on a single line.

Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0

Sample Output

8

题意就是给你一个带边权的树,求树上最短距离<=K的点对数量。树分治模板题。

代码:

 //树分治-点分治
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int inf=1e9+;
const int maxn=1e5+; int head[maxn],tot;
int root,allnode,ans,n,k;
int vis[maxn],deep[maxn],dis[maxn],siz[maxn],point[maxn];//deep[0]子节点个数(路径长度),point为重心节点 struct node{
int to,next,val;
}edge[maxn<<]; void add(int u,int v,int w)//前向星存图
{
edge[tot].to=v;
edge[tot].next=head[u];
edge[tot].val=w;
head[u]=tot++;
} void init()//初始化
{
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
tot=;
} void get_root(int u,int father)//重心
{
siz[u]=;point[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
get_root(v,u);//递归得到子树大小
siz[u]+=siz[v];
point[u]=max(point[u],siz[v]);//更新u节点的point
}
point[u]=max(point[u],allnode-siz[u]);//保存节点size
if(point[u]<point[root]) root=u;//更新当前子树的重心
} void get_dis(int u,int father)//获取子树所有节点与根的距离
{
deep[++deep[]]=dis[u];
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
int w=edge[i].val;
dis[v]=dis[u]+w;
get_dis(v,u);
}
} int cal(int u,int now)
{
dis[u]=now;deep[]=;
get_dis(u,);
sort(deep+,deep+deep[]+);
int all=;
for(int l=,r=deep[];l<r;){//二分
if(deep[l]+deep[r]<=k){
all+=r-l;l++;
}
else r--;
}
return all;
} void solve(int u)//以u为重心进行计算
{
ans+=cal(u,);//以当前u为重心的贡献
vis[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]) continue;
ans-=cal(v,edge[i].val);//减去子树的影响
allnode=siz[v];
root=;
get_root(v,u);
solve(root);
}
} int main()
{
while(~scanf("%d%d",&n,&k)&&n&&k){
init();
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
root=ans=;
allnode=n;point[]=inf;
get_root(,);
solve(root);
printf("%d\n",ans);
}
return ;
}

洛谷  P4178 Tree

一样的东西,就只是改了一下数据范围和输入格式。

代码:

 //树分治-点分治
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int inf=1e9+;
const int maxn=4e4+; int head[maxn],tot;
int root,allnode,ans,n,k;
int vis[maxn],deep[maxn],dis[maxn],siz[maxn],point[maxn];//deep[0]子节点个数(路径长度),point为重心节点 struct node{
int to,next,val;
}edge[maxn<<]; void add(int u,int v,int w)//前向星存图
{
edge[tot].to=v;
edge[tot].next=head[u];
edge[tot].val=w;
head[u]=tot++;
} void init()//初始化
{
memset(head,-,sizeof head);
memset(vis,,sizeof vis);
tot=;
} void get_root(int u,int father)//重心
{
siz[u]=;point[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
get_root(v,u);//递归得到子树大小
siz[u]+=siz[v];
point[u]=max(point[u],siz[v]);//更新u节点的point
}
point[u]=max(point[u],allnode-siz[u]);//保存节点size
if(point[u]<point[root]) root=u;//更新当前子树的重心
} void get_dis(int u,int father)//获取子树所有节点与根的距离
{
deep[++deep[]]=dis[u];
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father||vis[v]) continue;
int w=edge[i].val;
dis[v]=dis[u]+w;
get_dis(v,u);
}
} int cal(int u,int now)
{
dis[u]=now;deep[]=;
get_dis(u,);
sort(deep+,deep+deep[]+);
int all=;
for(int l=,r=deep[];l<r;){//二分
if(deep[l]+deep[r]<=k){
all+=r-l;l++;
}
else r--;
}
return all;
} void solve(int u)//以u为重心进行计算
{
ans+=cal(u,);//以当前u为重心的贡献
vis[u]=;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]) continue;
ans-=cal(v,edge[i].val);//减去子树的影响
allnode=siz[v];
root=;
get_root(v,u);
solve(root);
}
} int main()
{
scanf("%d",&n);
init();
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
scanf("%d",&k);
root=ans=;
allnode=n;point[]=inf;
get_root(,);
solve(root);
printf("%d\n",ans);
return ;
}

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

  1. POJ1471 Tree/洛谷P4178 Tree

    Tree P4178 Tree 点分治板子. 点分治就是直接找树的重心进行暴力计算,每次树的深度不会超过子树深度的\(\frac{1}{2}\),计算完就消除影响,找下一个重心. 所以伪代码: voi ...

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

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

  3. 洛谷P4178 Tree (点分治)

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

  4. 洛谷 P4178 Tree —— 点分治

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

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

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

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

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

  7. [洛谷P4178]Tree

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

  8. 洛谷 P4178 Tree

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

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

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

随机推荐

  1. Spring Boot 优雅的配置拦截器方式

    https://my.oschina.net/bianxin/blog/2876640 https://cs.xieyonghui.com/java/55.html 其实spring boot拦截器的 ...

  2. SpringBoot整合freemarker 引用基础

    原 ElasticSearch学习笔记Ⅲ - SpringBoot整合ES 新建一个SpringBoot项目.添加es的maven坐标如下: <dependency> <groupI ...

  3. 函数式接口java.util.function

    什么是函数式接口 为什么要用函数式接口 java.util.function和其他的函数式接口 lamdba表达式 方法引用 流 Stream 1 什么是函数式接口 用@FunctionInterfa ...

  4. Nikitosh 和异或(trie树)

    题目: #10051. 「一本通 2.3 例 3」Nikitosh 和异或 解析: 首先我们知道一个性质\(x\oplus x=0\) 我们要求\[\bigoplus_{i = l}^ra_i\]的话 ...

  5. permission

    import 'package:flutter/material.dart'; import 'dart:io'; import 'dart:async'; import 'package:rxdar ...

  6. Gson含抽象类的反序列化

    Gson含抽象类的反序列化 场景描述: 反序列化A类的时候,这个类里面有一个抽象类属性B,B的实现类C里面又有一个抽象类属性D,D的实现类是E 实体类准备 public class A impleme ...

  7. js动态替换和插入字符串

    替换 str是我要查询的内容loot.SERVE.file 是要被替换的内容g 全局替换"" 去替换的内容,我这里是空str.replace(new RegExp(loot.SER ...

  8. Guava Cache用法介绍

    背景 缓存的主要作用是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用.在日长开发有很多场合,有一些数据量不是很大,不会经常改动,并且访问非常频繁.但是由于受限于硬盘IO的性能或者远程网络 ...

  9. java requestmapping中关于路径的问题

    需要这种url写的方式才能映射

  10. Gerrit 服务器入门使用-项目的创建与克隆

    Gerrit 服务器入门使用-项目的创建与克隆 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.创建克隆项目 1>.点击"BROWSE" 2>.点 ...