题目链接【http://poj.org/problem?id=1741】

题意:

  给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数。

题解:

  这是一个很经典的树分治的题。假设我们选择了一个参考点u,那么对于不同的点对(u,v),(u , v)之间的路径有两种情况,经过点u,和不经过点u,加入我算出了没有经过点u的对数,然后把经过点u的加起来就是答案了,很简单,这就是分治的思想。具体看代码。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e4 + ;
int N, lit;
struct Edge
{
int to, next, len;
Edge() {}
Edge(int to, int next, int len): to(to), next(next), len(len) {}
} E[maxn * ];
int head[maxn], tot;
void initEdge()
{
for(int i = ; i <= N + ; i++) head[i] = -;
tot = ;
}
void addEdge(int u, int v, int len)
{
E[tot] = Edge(v, head[u], len);
head[u] = tot++; E[tot] = Edge(u, head[v], len);
head[v] = tot++;
}
int vis[maxn];
int dep[maxn], L, R;
int sz[maxn];
void GetSize(int u, int fa)
{
sz[u] = ;
for(int k = head[u]; ~k; k = E[k].next)
{
int v = E[k].to;
if(v == fa || vis[v]) continue;
GetSize(v, u);
sz[u] += sz[v];
}
}
void GetRoot(int u, int fa, int tot, int &rt)
{
int ma = tot - sz[u];
if(ma > tot / ) return ;
for(int k = head[u]; ~k; k = E[k].next)
{
int v = E[k].to;
if(v == fa || vis[v]) continue;
GetRoot(v, u, tot, rt);
ma = max(ma, sz[v]);
}
if(ma <= tot / ) rt = u;
}
void GetPath(int u, int fa, int len)
{
dep[R++] = len;
for(int k = head[u]; ~k; k = E[k].next)
{
int v = E[k].to;
if(v == fa || vis[v]) continue;
GetPath(v, u, len + E[k].len);
}
}
int GetNum(int L, int R)
{
int ret = ;
int pos = R - ;
sort(dep + L, dep + R);
for(int i = L; i < R; i++)
{
while(pos > i && dep[i] + dep[pos] > lit) pos--;
if(pos > i) ret += pos - i;
else break;
}
return ret;
}
int GetAns(int u)
{
int ret = , rt = ;
GetSize(u, -);
GetRoot(u, -, sz[u], rt);//找到重心
vis[rt] = ;//重心为分界点
for(int k = head[rt]; ~k; k = E[k].next)
{
int v = E[k].to;
if(vis[v]) continue;
ret += GetAns(v);//不过rt点的个数
}
L = R = ;
for(int k = head[rt]; ~k; k = E[k].next)
{
int v = E[k].to;
if(vis[v]) continue;
GetPath(v, rt, E[k].len);
ret -= GetNum(L, R);
L = R;
}
ret += GetNum(, R);
for(int i = ; i < R; i++)
if(dep[i] <= lit) ret++;
else break;
vis[rt] = ;
return ret;
}
int main ()
{
while(~scanf("%d %d", &N, &lit))
{
if(N == && lit == ) break;
initEdge();
for(int i = ; i < N; i++)
{
int u, v, len;
scanf("%d %d %d", &u, &v, &len);
addEdge(u, v, len);
}
int ans = GetAns();
printf("%d\n", ans);
}
return ;
}

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

  1. poj 1741 树的点分治(入门)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description ...

  2. poj 1741 树的分治

    思路:这题我是看 漆子超<分治算法在树的路径问题中的应用>写的. 附代码: #include<iostream> #include<cstring> #includ ...

  3. POJ 1741 树的点分治

    题目大意: 树上找到有多少条路径的边权值和>=k 这里在树上进行点分治,需要找到重心保证自己的不会出现过于长的链来降低复杂度 #include <cstdio> #include & ...

  4. POJ 1741 [点分治][树上路径问题]

    /* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给一棵有n个节点的树,每条边都有一个正权值,求一共有多少个点对使得它们之间路的权值和小于给定的k. 思路: <分治算法在树的路径问题中的应用 ...

  5. [八分之三的男人] POJ - 1741 点分治 && 点分治笔记

    题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...

  6. POJ 1741 点分治

    方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...

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

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

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

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

  9. POJ 1741 Tree【树分治】

    第一次接触树分治,看了论文又照挑战上抄的代码,也就理解到这个层次了.. 以后做题中再慢慢体会学习. 题目链接: http://poj.org/problem?id=1741 题意: 给定树和树边的权重 ...

随机推荐

  1. Redis实战(六)管道

    https://www.cnblogs.com/huangxincheng/p/6212406.html

  2. 原生js写Ajax

    //原生js写ajax就像打电话 //打电话分下面4步//1.拿出手机//2.拨号//3.说话//4.挺对方说话 //ajax也分下面4步//1.创建ajax对象//2.连接到服务器//3.发送请求( ...

  3. An impassioned circulation of affection(尺取+预处理)

    题目链接:http://codeforces.com/contest/814/problem/C 题目: 题意:给你一个长度为n的字符串,m次查询,每次查询:最多进行k步修改,求字符c(要输入的字符) ...

  4. uboot1.1.6 start.s分析

    .Stage1 start.S代码结构 u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:(1)定义入口.由于一个可执行的Image必须有一个入口点,并 ...

  5. BeanPostProcessor的五大接口

    BeanPostProcessor 关于对象初始化前后的回调. public interface BeanPostProcessor { //该方法在bean实例化完毕(且已经注入完毕),在after ...

  6. sniffer简单使用

    跟wireshark类似. 只是说显示的容易忘记所以丢张图记录一下. 该工具还是很坑爹的,不是比赛要用到所以都不是很想弄.一般机器运行不起来.不是蓝屏就是装了运行不了各种闪退,找了学校一台内网服务器才 ...

  7. USB各种模式 解释

    1.MTP: 通过MTP这种技术,可以把音乐传到手机里.有了U盘功能为什么还要多此一举呢?因为版权问题,MTP可以把权限文件从电脑上导过去:如果只使用手机的U盘功能,把歌的文件拷过去之后,没有权限文件 ...

  8. 2017 SWERC

    2017 SWERC A:Cakey McCakeFace 题目描述:有一个炉每次只能放一个蛋糕,炉的进口和出口各放了一个探测器,当放蛋糕进去时,进口的探测器会记录时刻,当蛋糕做好后,蛋糕从出口出来, ...

  9. Linux阵列 RAID详解 (转)

    原文链接:http://molinux.blog.51cto.com/2536040/516008   一. RAID详解   二. mdadm工具介绍   三. 创建一个RAID的基本过程   四. ...

  10. TreeSet基本用法

    TreeSet的基础方法: public class TreeSetTest { public static void main(String[] args) { TreeSet nums = new ...