传送门:http://poj.org/problem?id=1741

写的第一道树分治题,撒花纪念~

对于每一对点对(i, j),它有三种情况:

① 其中一个是根节点。这种情况比较简单,直接加上就好了。

② 横跨根节点。这种情况是重点。

③ 不是以上两种情况。这时递归下去求解就好了。

那么对于第二种情况该怎么破呢?设根节点为root,那么dist(i, root) + dist(j, root) <= k,且需要i与j在不同的子树里。直接算不同子树的点对(i, j)的个数会麻烦,所以需要一点技巧:符合条件且在不同子树的(i, j)的对数 = 符合条件的对数 - 符合条件且在相同子树的(i, j)的对数,这样就搞定啦!

#include <cstdio>
#include <cstring>
#include <algorithm> const int maxn = 10005; int n, k, t1, t2, t3, ans;
int head[maxn], to[maxn << 1], next[maxn << 1], w[maxn << 1], lb;
int siz[maxn], a[maxn], left, right;
bool book[maxn]; inline void ist(int aa, int ss, int ww) {
to[lb] = ss;
next[lb] = head[aa];
head[aa] = lb;
w[lb] = ww;
++lb;
}
int fnd_zx(int fr, int tot_node, int p, int & rt, int & mn) {
int mx = 0;
for (int j = head[fr]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
fnd_zx(to[j], tot_node, fr, rt, mn);
mx = std::max(mx, siz[to[j]]);
}
}
mx = std::max(mx, tot_node - siz[fr]);
if (mn > mx) {
mn = mx;
rt = fr;
}
}
void get_siz(int fr, int p) {
siz[fr] = 1;
for (int j = head[fr]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
get_siz(to[j], fr);
siz[fr] += siz[to[j]];
}
}
}
void get_data(int r, int p, int ww) {
if (ww > k) {
return;
}
a[right++] = ww;
for (int j = head[r]; j != -1; j = next[j]) {
if (!book[to[j]] && to[j] != p) {
get_data(to[j], r, ww + w[j]);
}
}
}
int get_ans(int l, int r) {
std::sort(a + l, a + r);
int rt = 0;
--r;
while (r > l) {
while (r > l && a[l] + a[r] > k) {
--r;
}
rt += r - l;
++l;
}
return rt;
}
void slove(int fr) {
int root = -666, mn = 2147483647;
get_siz(fr, 0);
fnd_zx(fr, siz[fr], 0, root, mn);
book[root] = true;
for (int j = head[root]; j != -1; j = next[j]) {
if (!book[to[j]]) {
slove(to[j]);
}
}
left = right = 0;
for (int j = head[root]; j != -1; j = next[j]) {
if (!book[to[j]]) {
get_data(to[j], root, w[j]);
ans -= get_ans(left, right);
left = right;
}
}
ans += get_ans(0, right) + right;
book[root] = false;
} int main(void) {
//freopen("in.txt", "r", stdin);
while (scanf("%d%d", &n, &k) && n && k) {
lb = 0;
memset(head, -1, sizeof head);
memset(next, -1, sizeof next);
ans = 0;
for (int i = 1; i < n; ++i) {
scanf("%d%d%d", &t1, &t2, &t3);
ist(t1, t2, t3);
ist(t2, t1, t3);
}
slove(1);
printf("%d\n", ans);
}
return 0;
}

  

[POJ1741] Tree【树分治 点分治】的更多相关文章

  1. POJ1741——Tree(树的点分治)

    1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-11-17 1 ...

  2. 【poj1741】Tree 树的点分治

    题目描述 Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dis ...

  3. hdu 4812 D Tree(树的点分治)

    D Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total ...

  4. [poj1741][tree] (树/点分治)

    Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Def ...

  5. POJ1741 Tree 树分治模板

    http://poj.org/problem?id=1741   题意:一棵n个点的树,每条边有距离v,求该树中距离小于等于k的点的对数.   dis[y]表示点y到根x的距离,v代表根到子树根的距离 ...

  6. POJ1741(SummerTrainingDay08-G 树的点分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23380   Accepted: 7748 Description ...

  7. hdu4812-D Tree (树的点分治)

    昨天学了下树分治,今天补这道题,还是太不熟练了,写完之后一直超时.后来查出好多错= =比如v,u写倒了,比如+写成了取最值,比如....爆int...查了两个多小时的错..哭...(没想到进首页了 h ...

  8. 【POJ 1741】 Tree (树的点分治)

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

  9. 树上点对统计poj1741(树的点分治)

    给定一棵树,边上有权值,要统计有多少对点路径的权值和<=k 分治算法在树的路径中的应用 这个论文里面有分析. 任意两点的路径,要么过根结点,要么在子树中.如果在子树中,那么只要递归处理就行了. ...

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

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

随机推荐

  1. [转] Oracle数据库维护常用SQL语句集合

           原文地址 进程相关: 1. 求当前会话的SID,SERIAL# SELECT Sid, Serial# FROM V$session WHERE Audsid = Sys_Context ...

  2. CTEX - 在线文档 - TeX/LaTeX 常用宏包

    CTEX - 在线文档 - TeX/LaTeX 常用宏包       页面与章节标题式样   浮动对象及标题设计   生成与插入图形   表格与列表   目录与索引   参考文献   数学与化学公式 ...

  3. 关于Chrome谷歌浏览器开发者工具网络Network中返回无数据的问题

    1.如图所示,对于有些js文件,响应中无返回数据,Failed to load response data,当然本来是应该有数据,你用火狐浏览器看,就是有的,或者直接在浏览器地址栏里输入url,也可以 ...

  4. Linux中断处理驱动程序编写

    本章节我们一起来探讨一下Linux中的中断 中断与定时器:中断的概念:指CPU在执行过程中,出现某些突发事件急待处理,CPU暂停执行当前程序,转去处理突发事件,处理完后CPU又返回原程序被中断的位置继 ...

  5. php.ini中extension默许的地址到底在哪里设置的

    原文: http://www.myexception.cn/php/1436096.html ----------------------------------------------------- ...

  6. HDU 1017 A Mathematical Curiosity【看懂题意+穷举法】

    //2014.10.17    01:19 //题意: //先输入一个数N,然后分块输入,每块输入每次2个数,n,m,直到n,m同一时候为零时  //结束,当a和b满足题目要求时那么这对a和b就是一组 ...

  7. curl_setopt GET的方法

    $ch ") ; curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; curl_setopt($ch, CURLOPT_BINARYTRANSF ...

  8. Ioc 器管理的应用程序设计,前奏:容器属于哪里? 控制容器的反转和依赖注入模式

    Ioc 器管理的应用程序设计,前奏:容器属于哪里?   我将讨论一些我认为应该应用于“容器管理”应用程序设计的原则. 模式1:服务字典 字典或关联数组是我们在软件工程中学到的第一个构造. 很容易看到使 ...

  9. 深刻理解Java中形參与实參,引用与对象的关系

    声明:本博客为原创博客,未经同意.不得转载! 原文链接为http://blog.csdn.net/bettarwang/article/details/30989755 我们都知道.在Java中,除了 ...

  10. Thinkpad升级Window10无法安装expresscache

    本人有一台Thinkpad T440s,自从看了这篇帖子12秒开机!ExpressCache SSD缓存加速,就给自己的小黑加持了一块固态硬盘.使用后效果确实很明显. 问题 自从系统自动升级到wind ...