题目链接【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. PHP做文件限速下载

    <?php include("DBDA.class.php"); $db = new DBDA(); $bs = $_SERVER["QUERY_STRING&qu ...

  2. WordPress手机端插件——WPtouch

    戒微博之后,把更多的精力开始转投回网站上来:今天用nexus7访问@Bee君 的博客时,发现博客的界面与电脑上访问的界面不相同,顺藤摸瓜之后发现原来bee君使用的是WPtouch-pro插件来实现移动 ...

  3. 无key值的json数组解析

    [    [        {            "cartId": 9223,            "factoryId": 143,          ...

  4. Django 自定义分页类

    分页类代码: class Page(object): ''' 自定义分页类 可以实现Django ORM数据的的分页展示 输出HTML代码: 使用说明: from utils import mypag ...

  5. 【Python学习】request库

    Requests库(https://www.python-requests.org/)是一个擅长处理那些复杂的HTTP请求.cookie.header(响应头和请求头)等内容的Python第三方库. ...

  6. 【转载】WebDriver(C#)之十点使用心得

    使用Selenium WebDriver驱动浏览器测试的过程中多多少少会遇到一些折腾人的问题,总结了一部分,做下分享. 一.隐藏元素处理(element not visible) 使用WebDrive ...

  7. Deep Learning基础--各个损失函数的总结与比较

    损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好.损失函数是经验 ...

  8. openjudge-NOI 2.6-1996 登山

    题目链接:http://noi.openjudge.cn/ch0206/1996/ 题解: 正反求两次LIS即可 #include<cstdio> #include<cstring& ...

  9. acm专题---最小生成树

    kruscal(eloge): 题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1102 Problem Description There are N ...

  10. TCP封包解包---如有错误,请纠正!

    最近遇见很多的关于TCP中封包解包的数据,在TCP节点之间的信息传递,每次传送的内容是结构体,所以每次在传送的时候,要将结构体中的数据进行封包,然后当一端接收到数据之后,要对接收到的buf参数中的数据 ...