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.

题目大意:给一个带边权的树,问有多少对点满足dist(i,j)<=k

思路:可以参考2009年的国家集训队论文《分治算法在树的路径问题中的应用》——漆子超。

代码(188MS):

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std; const int MAXN = ;
const int MAXE = ;
const int INF = 0x7fff7fff; int head[MAXN], size[MAXN], maxSize[MAXN];
int list[MAXN], cnt;
bool del[MAXN];
int to[MAXE], next[MAXE], cost[MAXE];
int n, k, ecnt; void init() {
memset(head, -, sizeof(head));
memset(del, , sizeof(del));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cost[ecnt] = c; next[ecnt] = head[v]; head[v] = ecnt++;
} void dfs1(int u, int f) {
size[u] = ;
maxSize[u] = ;
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(v == f || del[v]) continue;
dfs1(v, u);
size[u] += size[v];
maxSize[u] = max(maxSize[u], size[v]);
}
list[cnt++] = u;
} int get_root(int u, int f) {
cnt = ;
dfs1(u, f);
int ret, maxr = INF;
for(int i = ; i < cnt; ++i) {
int &x = list[i];
if(max(maxSize[x], size[u] - size[x]) < maxr) {
ret = x;
maxr = max(maxSize[x], size[u] - size[x]);
}
}
return ret;
} void dfs2(int u, int f, int dis) {
list[cnt++] = dis;
for(int p = head[u]; ~p; p = next[p]) {
int &v = to[p];
if(v == f || del[v]) continue;
dfs2(v, u, dis + cost[p]);
}
} int calc(int a, int b) {
int j = b - , ret = ;
for(int i = a; i < b; ++i) {
while(list[i] + list[j] > k && i < j) --j;
ret += j - i;
if(j == i) break;
}
return ret;
} int ans = ; void work(int u, int f) {
int root = get_root(u, f);
del[root] = true;
int last = ; cnt = ;
for(int p = head[root]; ~p; p = next[p]) {
int &v = to[p];
if(del[v]) continue;
dfs2(v, root, cost[p]);
sort(list + last, list + cnt);
ans -= calc(last, cnt);
last = cnt;
}
list[cnt++] = ;
sort(list, list + cnt);
ans += calc(, cnt);
for(int p = head[root]; ~p; p = next[p]) {
int &v = to[p];
if(del[v]) continue;
work(v, root);
}
} int main() {
while(scanf("%d%d", &n, &k) != EOF) {
if(n == && k == ) break;
init();
for(int i = ; i < n; ++i) {
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
add_edge(u, v, c);
}
ans = ;
work(, );
printf("%d\n", ans);
}
}

POJ 1741 Tree(树的分治)的更多相关文章

  1. POJ 1741 Tree 树的分治

    原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...

  2. poj 1741 Tree (树的分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30928   Accepted: 10351 Descriptio ...

  3. POJ 1741 Tree 树的分治(点分治)

    题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...

  4. POJ 1741.Tree 树分治 树形dp 树上点对

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 24258   Accepted: 8062 Description ...

  5. POJ 1741 Tree(树的点分治,入门题)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 21357   Accepted: 7006 Description ...

  6. POJ 1741 Tree 树分治

    Tree     Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...

  7. POJ 1741 Tree 树上点分治

    题目链接:http://poj.org/problem?id=1741 题意: 给定一棵包含$n$个点的带边权树,求距离小于等于K的点对数量 题解: 显然,枚举所有点的子树可以获得答案,但是朴素发$O ...

  8. POJ 1741 Tree (点分治)

                                                                        Tree Time Limit: 1000MS   Memory ...

  9. poj 1741 Tree(点分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 15548   Accepted: 5054 Description ...

  10. poj 1741 Tree(树的点分治)

    poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...

随机推荐

  1. webpack报错Cannot read property 'presetToOptions' of undefined

    在学习react全家桶时,webpack首先报错,报错内容如下,最后我是因为没有全局安装webpack导致的报错,使用npm install webpack -g安装解决了这个问题.

  2. Wireshark抓取Mqtt报文

    安装版本较高的Wireshark,我的版本是2.4.6,然后在编辑--> 首选项--> 协议中找到MQTT,然后将端口改为你MQTT服务器的端口,然后就可以在抓包中抓到MQTT了

  3. .Net 上传文件到ftp服务器和下载文件

    突然发现又很久没有写博客了,想起哎呦,还是写一篇博客记录一下吧,虽然自己还是那个渣渣猿. 最近在做上传文件的功能,上传到ftp文件服务器有利于管理上传文件. 前面的博客有写到layui如何上传文件,然 ...

  4. SkipList 之详细分析

    SkipList 俗称跳表,跳表是一种随机化的数据结构,目前开源软件 Redis 和 LevelDB 都有用到它,它的效率和红黑树以及 AVL 树不相上下,但跳表的原理相当简单,只要你能熟练操作链表, ...

  5. 『Python基础-15』递归函数 Recursion Function

    什么是递归函数 一种计算过程,如果其中每一步都要用到前一步或前几步的结果,称为递归的.用递归过程定义的函数,称为递归函数,例如连加.连乘及阶乘等.凡是递归的函数,都是可计算的,即能行的. 递归就是一个 ...

  6. Leecode刷题之旅-C语言/python-217存在重复元素

    /* * @lc app=leetcode.cn id=217 lang=c * * [217] 存在重复元素 * * https://leetcode-cn.com/problems/contain ...

  7. golang 协程嵌套,会产生依赖关系(父子关系)么?

    编码时冒出一个问题:在一个协程内部,再创建一个或多个协程,是否会产生依赖关系? 做了一个小实验,这里随笔记录一下经过,备注后续深入研究. test代码: package main import ( & ...

  8. 成都Uber优步司机奖励政策(2月16日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  9. [Jmeter并发报错解决方案]org.apache.http.NoHttpResponseException: 10.0.4.147:8000 failed to respond

    背景:公司模型框架是Nginx+uwsgi+Django+nginx,一开始使用Jmeter进行高并发请求测试,发现成功率只有50%,换用postman,成功率100%,代码进行高并发一样不会报错. ...

  10. cakephp2.x 一个ajax例子.md

    CakePHP中的ajax还是比较简单,但要注意一些细节. app/View/Layouts下新建ajaxtest.ctp <!DOCTYPE html PUBLIC "-//W3C/ ...