[POJ1741]树上的点对 树分治
Description
给一棵有n个节点的树,每条边都有一个长度(小于1001的正整数)。
定义dist(u,v)=节点u到节点v的最短路距离。
给出一个整数k,我们称顶点对(u,v)是合法的当且仅当dist(u,v)不大于k。
写一个程序,对于给定的树,计算有多少对顶点对是合法的。
Input
输入包含多组数据。
每组数据的第一行有两个整数N,K(N<=10000)。接下来N-1行每行有三个整数u,v,l,代表节点u和v之间有一条长度l的无向边。
输入结束标志为N=K=0.
Output
对每组数据输出一行一个正整数,即合法顶点对的数量。
Sample Input
5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output
8
树分治裸题:
每一次找到树的重心,使得二分复杂度降为logn,然后每一个小区间做相同处理:
设 dis[i]表示到当前根节点X的距离 找到以当前节点X为根的满足dis[i]+dis[j]<=k的所有方案。
在统计的时候可能存在把同一子树满足dis[i]+dis[j]<=k的也统计进答案中,产生重复方案。
于是我们要减去每一棵子树中满足dis[i]+dis[j]<=k的方案。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; int n,k; int gi()
{
int str=;char ch=getchar();
while(ch>'' || ch<'')ch=getchar();
while(ch>='' && ch<='')str=str*+ch-'',ch=getchar();
return str;
} const int N=;int sum=;int ans=;
int num=,head[N];int root=;int son[N];int f[N]={};bool vis[N];int dis[N];
int b[N];
struct Lin
{
int next,to,dis;
}a[N*]; void init(int x,int y,int z)
{
a[++num].next=head[x];
a[num].to=y;
a[num].dis=z;
head[x]=num;
} void getroot(int x,int last)
{
son[x]=;f[x]=;
int u;
for(int i=head[x]; i ;i=a[i].next)
{
u=a[i].to;
if(u==last || vis[u])continue;
getroot(u,x);
son[x]+=son[u];
f[x]=max(f[x],son[u]);
}
f[x]=max(f[x],sum-son[x]);
if(f[x]<f[root])root=x;
return ;
} void getdis(int x,int last)
{
int u;
b[++b[]]=dis[x];
for(int i=head[x];i;i=a[i].next)
{
u=a[i].to;
if(u==last || vis[u])continue;
dis[u]=dis[x]+a[i].dis;
getdis(u,x);
}
return ;
} int cal(int x,int dd)
{
int tot=,u;dis[x]=dd;
b[]=;
getdis(x,);
sort(b+,b+b[]+);
int l=,r=b[];
while(l<r)
{
if(b[l]+b[r]<=k)tot+=r-l,l++;
else r--;
}
return tot;
} void work(int x)
{
ans+=cal(x,);
vis[x]=;
int u;
for(int i=head[x];i;i=a[i].next)
{
u=a[i].to;
if(vis[u])continue;
ans-=cal(u,a[i].dis);
root=;sum=son[u];
getroot(u,x);
work(root);
}
return ;
} void Clear()
{
memset(vis,,sizeof(vis));
f[]=;
memset(a,,sizeof(a));
memset(head,,sizeof(head));
memset(dis,,sizeof(dis));
num=;
}
int main()
{
while(scanf("%d%d",&n,&k))
{
if(!n && !k)return ;
int x,y,z;
Clear();
for(int i=;i<=n-;i++)
{
x=gi();y=gi();z=gi();
init(x,y,z);init(y,x,z);
}
sum=n;
ans=;
root=;
getroot(,);
work(root);
printf("%d\n",ans);
}
return ;
}
[POJ1741]树上的点对 树分治的更多相关文章
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- POJ1741:Tree——题解+树分治简要讲解
http://poj.org/problem?id=1741 题目大意:给一棵树,求点对间距离<=k的个数. ———————————————————— 以这道题为例记录一下对于树分治的理解. 树 ...
- POJ1741 经典树分治
题意:有一棵树,每条边有一个距离,求dis(u,v)<=k的点的对数 题解:树分治,对于一颗树上的两点,要么在同一颗子树上,要么在不同子树上,要么一个点是根,另一个在某一子树上,对于第一种情况我 ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- 树分治&树链剖分相关题目讨论
预备知识 树分治,树链剖分 poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...
- 树分治learning
学习了树的点分治,树的边分治似乎因为复杂度过高而并不出众,于是没学 自己总结了一下 有些时候面对一些树上的结构 并且解决的是和路径有关的问题的时候 如果是多个询问 关注点在每次给出两个点,求一些关于这 ...
- UVALive 7148 LRIP【树分治+线段树】
题意就是要求一棵树上的最长不下降序列,同时不下降序列的最小值与最大值不超过D. 做法是树分治+线段树,假设树根是x,y是其当前需要处理的子树,对于子树y,需要处理出两个数组MN,MX,MN[i]表示以 ...
- COJ 0970 WZJ的数据结构(负三十)树分治
WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计 ...
- Poj1741-Tree(树分治)
题意:找树上有多少对距离小于K的对数解析:树分治模板题,见注释 代码 #include<cstdio> #include<cstring> #include<string ...
随机推荐
- 作业07-Java GUI编程
1. 本周学习总结 1.1 思维导图:Java图形界面总结 1.2 可选:使用常规方法总结其他上课内容. 关于事件.事件源.事件监听器的总结: 事件:用户在GUI上进行的操作,如鼠标单击.输入文字.关 ...
- 20145237 实验二 “Java面向对象程序设计”
20145237 实验二 “Java面向对象程序设计” 实验内容 • 理解并掌握面向对象三要素:封装.继承.多态 • 初步掌握UML建模 • 熟悉S.O.L.I.D原则 • 使用TDD设计实现复数类 ...
- Papers3
Papers3 总览 Papers功能主要是文献收集,整理,阅读和引用. 主页面: 文献收集 Papers提供两种导入文献的方法:在线搜索和本地导入: 在线搜索 可以通过搜索题目,作者,摘要等内容中的 ...
- git基本用法
基本用法(下) 一.实验说明 本节实验为 Git 入门第二个实验,继续练习最常用的git命令. 1.1 实验准备 在进行该实验之前,可以先clone一个练习项目gitproject ...
- 使用SecureCRTP 连接生产环境的web服务器和数据库服务器
一.使用SecureCRTP 连接生产环境的web服务器 首先,需要知道以下参数信息: 1.web服务器的ip地址 2.服务器的端口号 3.会话连接的用户名和密码 4.服务器的用户名 ...
- 第四十六条:for-each循环优先于传统的for循环
for(Elements e : list) { //doSomeThing-- }
- LR录制脚本的时候打不开浏览器问题
使用Chrome时,显示开始录制但是Action中无任何脚本,即脚本没成功生成. 使用Firefox(最新版),一直关闭程序,详细信息有StackHash_0a9e. 使用IE11时,也是显示开始录制 ...
- :after/:before使用技巧
伪类:after/:before基本使用 div:before{ content:'';//必须要写,没写则伪元素无效 display:; position:''; ... } //在一个div子元素 ...
- 剑指offer-数组中出现次数超过一半的数字
题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...
- api-gateway实践(15)API网关的待改进点 20171207
一.API网关能力 API网关负责服务请求路由.组合及协议转换.客户端的所有请求都首先经过API网关,然后由它将请求路由到合适的微服务.API网关的客户端通过统一的网关接入微服务,在网关层处理所有的非 ...