POJ 1741 树分治
题目链接【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 树分治的更多相关文章
- poj 1741 树的点分治(入门)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 18205 Accepted: 5951 Description ...
- poj 1741 树的分治
思路:这题我是看 漆子超<分治算法在树的路径问题中的应用>写的. 附代码: #include<iostream> #include<cstring> #includ ...
- POJ 1741 树的点分治
题目大意: 树上找到有多少条路径的边权值和>=k 这里在树上进行点分治,需要找到重心保证自己的不会出现过于长的链来降低复杂度 #include <cstdio> #include & ...
- POJ 1741 [点分治][树上路径问题]
/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给一棵有n个节点的树,每条边都有一个正权值,求一共有多少个点对使得它们之间路的权值和小于给定的k. 思路: <分治算法在树的路径问题中的应用 ...
- [八分之三的男人] POJ - 1741 点分治 && 点分治笔记
题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...
- POJ 1741 点分治
方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...
- POJ 1741.Tree 树分治 树形dp 树上点对
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 24258 Accepted: 8062 Description ...
- poj 1741 Tree(树的点分治)
poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
- POJ 1741 Tree【树分治】
第一次接触树分治,看了论文又照挑战上抄的代码,也就理解到这个层次了.. 以后做题中再慢慢体会学习. 题目链接: http://poj.org/problem?id=1741 题意: 给定树和树边的权重 ...
随机推荐
- 部署维护docker环境
其实前面已经用salt,安装部署了docker应用环境了,过程中还是遇到了不少问题,所以这里再相对仔细的记录一下,docker手机安装过程应注意的事情 安装过程部分参考了刘天斯大师文档部署 1,安装环 ...
- CentOS7 升级gcc版本
CentOS7自带的GCC版本是4.8.5,如下所示: # cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) # which g ...
- Attention is all you need 论文详解(转)
一.背景 自从Attention机制在提出之后,加入Attention的Seq2Seq模型在各个任务上都有了提升,所以现在的seq2seq模型指的都是结合rnn和attention的模型.传统的基于R ...
- Linux内核中的队列 kfifo【转】
转自:http://airekans.github.io/c/2015/10/12/linux-kernel-data-structure-kfifo#api 在内核中经常会有需要用到队列来传递数据的 ...
- sshpass-免交互SSH登录工具
sshpass用于自动向命令行提供密码,适用于ssh,scp,rsync,pssh,pscp等ssh系列的命令和工具 #安装sshpass yum install sshpass -y #注:当第一次 ...
- 安装mysql驱动之 mysqlclient 出现的报错处理(ubuntu16.04)
首先 更新软件! sudo apt-get update 然后尝试安装mysqlclient,报错 后执行下面的步骤 安装mysql驱动之 mysqlclient 出现的报错信息处理 报错1: OSE ...
- JAVA封装消息中间件调用二(kafka消费者篇)
上一遍我简单介绍了kafka的生成者使用,调用方式比较简单,今天我给大家分享下封装kafka消费者,作为中间件,我们做的就是最大程度的解耦,使业务方接入我们依赖程度降到最低. 第一步,我们先配置一个消 ...
- windows 下安装 nginx + php
1. 下载软件 需要的软件有nginx,php,mysql(如不需要可不安装) nginx.org,www.php.net上面有得下 全部解压出来 php基本不用做任何修改(下载直接解压版本的) 用c ...
- [你必须知道的.NET]第二十三回:品味细节,深入.NET的类型构造器
发布日期:2008.11.2 作者:Anytao © 2008 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 今天Artech兄在<关于Type Init ...
- 基于Token的授权(with srping mvc)
@Override public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOExce ...