POJ 1741 Tree(树的分治)
Description
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 last test case is followed by two zeros.
Output
题目大意:给一个带边权的树,问有多少对点满足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(树的分治)的更多相关文章
- POJ 1741 Tree 树的分治
原题链接:http://poj.org/problem?id=1741 题意: 给你棵树,询问有多少点对,使得这条路径上的权值和小于K 题解: 就..大约就是树的分治 代码: #include< ...
- poj 1741 Tree (树的分治)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 30928 Accepted: 10351 Descriptio ...
- POJ 1741 Tree 树的分治(点分治)
题目大意:给出一颗无根树和每条边的权值,求出树上两个点之间距离<=k的点的对数. 思路:树的点分治.利用递归和求树的重心来解决这类问题.由于满足题意的点对一共仅仅有两种: 1.在以该节点的子树中 ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
- POJ 1741 Tree 树分治
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 1 ...
- POJ 1741 Tree 树上点分治
题目链接:http://poj.org/problem?id=1741 题意: 给定一棵包含$n$个点的带边权树,求距离小于等于K的点对数量 题解: 显然,枚举所有点的子树可以获得答案,但是朴素发$O ...
- POJ 1741 Tree (点分治)
Tree Time Limit: 1000MS Memory ...
- poj 1741 Tree(点分治)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 15548 Accepted: 5054 Description ...
- poj 1741 Tree(树的点分治)
poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
随机推荐
- c#聊聊文件数据库kv
现在有很多KV嵌入式存储,或者已经增加的.leveldb,RaptorDB等,都是相对比较好的存储.基本存储,一般配置.大概在6w/s左右.当然还有缓存等设置问题.这些基本是字符串和int的存储,对于 ...
- webpack之理解loader
我们在写webpack配置文件的时候,应该有注意到经常用到loader这个配置项,那么loader是用来做什么的呢? loader其实是用来将源文件经过转化处理之后再输出新文件. 如果是数组形式的话, ...
- 463. Island Perimeter (5月29日)
解答 class Solution { public: int islandPerimeter(vector<vector<int>>& grid) { int num ...
- ubuntu网卡配置及安装ssh服务
1.ubuntu网卡配置 1.查看网卡名称 ip a 2.进行编辑网卡配置文件 sudo vi /etc/network/interfaces 更改网卡配置文件添加内容修改内容如下:下面的enp0s3 ...
- Java 创建线程的方式
想必大家在Java面试中经常会被问到有关线程的问题,最常见的莫过于“Java有哪几种创建线程的方式呢?” 稍稍了解过,或者在日常开发中也都会用到以下几种方式: ①继承Thread类(真正意义上的线程类 ...
- 【小尝试】Java获取慕课网原有路径课程列表
作为一个老慕课网(https://www.imooc.com/)粉丝,还记得最开始的慕课网有很多免费的路径课程,练习什么的也特别详细,是入门一门语言的好方法. 现在慕课网发展起来了收费模式,添加了很多 ...
- 前端js转换时间戳为时间类型显示
//时间戳转换 function add0(m){return m<10?'0'+m:m } function formatDate(timestamp) { //timestamp是整数,否则 ...
- html5中audio支持音频格式
HTML5 Audio标签能够支持wav, mp3, ogg, acc, webm等格式,但有个很重要的音乐文件格式midi(扩展名mid)却在各大浏览器中都没有内置的支持.不是所有的浏览器都支持MP ...
- openwrt procd启动流程和脚本分析
Linux内核执行start_kernel函数时会调用kernel_init来启动init进程,流程如下图: graph LR A[start_kernel] -->B(rest_init) B ...
- 组播___IGMP
一.基本概念: 1.协议概述: 是运行在主机和与主机直连的路由器之间,其实现的功能是双向的:一方面,主机通过IGMP通知路由器希望接收某个特定组播组的信息:另一方面,路由器通过IGMP周期性地查询局域 ...