poj 1741
点分治入门题
首先发现是树上点对的问题,那么首先想到上点分治
然后发现题目要求是求出树上点对之间距离小于等于k的对数,那么我们很自然地进行分类:
对于一棵有根树,树上的路径只有两种:一种经过根节点,另一种不经过根节点
对于经过根节点的路径,我们可以通过计算出每个点的根节点的距离,然后相加就能求出点对间距离
对于不经过根节点的路径,我们可以递归到子节点去算,去找子节点对应的子树来算即可
但是这里有两个问题:第一,如何快速算出以一个点为根的合法点对数量?
我们知道,可以在线性时间内求出每个点到根节点的距离,但如果我们逐个枚举点对的话,时间就会退化成平方级别
这显然不够优秀
所以我们将每个点到根节点距离排序,然后用两个指针,初始分别指向头和尾,如果两个指针指到的之和是合法的,那么这两个指针间的部分都是合法的(具体看代码),扫一遍即可
第二:这样做的结果是正确的吗?
我们看到,如果查到的一个点对在同一棵子树内,那么在计算以这个点为根和以这个点的子节点为根的时候,这个点对都会被计算一次!
这显然是不对的
因此我们在枚举每个子树时需要先去掉这一部分,然后再计算
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
struct Edge
{
int next;
int to;
int val;
}edge[];
int head[];
int rt,s;
int n,k;
int maxp[];
int siz[];
bool vis[];
int dis[];
int used[];
int ans=;
int cnt=;
void init()
{
memset(head,-,sizeof(head));
memset(vis,,sizeof(vis));
ans=;
cnt=;
}
void add(int l,int r,int w)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
head[l]=cnt++;
}
void get_rt(int x,int fa)
{
siz[x]=,maxp[x]=;
for(int i=head[x];i!=-;i=edge[i].next)
{
int to=edge[i].to;
if(vis[to]||to==fa)continue;
get_rt(to,x);
siz[x]+=siz[to];
maxp[x]=max(maxp[x],siz[to]);
}
maxp[x]=max(maxp[x],s-siz[x]);
if(maxp[x]<maxp[rt])rt=x;
}
void get_dis(int x,int fa)
{
used[++used[]]=dis[x];
for(int i=head[x];i!=-;i=edge[i].next)
{
int to=edge[i].to;
if(vis[to]||to==fa)continue;
dis[to]=dis[x]+edge[i].val;
get_dis(to,x);
}
}
int calc(int x,int val)
{
dis[x]=val;
used[]=;
get_dis(x,);
sort(used+,used+used[]+);
int l=,r=used[];
int ret=;
while(l<r)
{
if(used[l]+used[r]<=k)ret+=r-l,l++;
else r--;
}
return ret;
}
void solve(int x)
{
vis[x]=;
ans+=calc(x,);
for(int i=head[x];i!=-;i=edge[i].next)
{
int to=edge[i].to;
if(vis[to])continue;
ans-=calc(to,edge[i].val);
rt=,s=siz[to],maxp[rt]=inf;
get_rt(to,);
solve(rt);
}
}
int main()
{
while()
{
scanf("%d%d",&n,&k);
init();
if(!n&&!k)return ;
for(int i=;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
maxp[rt]=s=n;
get_rt(,);
solve(rt);
printf("%d\n",ans);
}
return ;
}
poj 1741的更多相关文章
- 【POJ 1741】 Tree (树的点分治)
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...
- poj 1741 树的点分治(入门)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 18205 Accepted: 5951 Description ...
- POJ 1741 Tree 求树上路径小于k的点对个数)
POJ 174 ...
- poj 1741 Tree(树的点分治)
poj 1741 Tree(树的点分治) 给出一个n个结点的树和一个整数k,问有多少个距离不超过k的点对. 首先对于一个树中的点对,要么经过根结点,要么不经过.所以我们可以把经过根节点的符合点对统计出 ...
- poj 1741 楼教主男人八题之中的一个:树分治
http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...
- 树的点分治 (poj 1741, 1655(树形dp))
poj 1655:http://poj.org/problem?id=1655 题意: 给无根树, 找出以一节点为根, 使节点最多的树,节点最少. 题解:一道树形dp,先dfs 标记 所有节点的子 ...
- POJ 1741.Tree and 洛谷 P4178 Tree-树分治(点分治,容斥版) +二分 模板题-区间点对最短距离<=K的点对数量
POJ 1741. Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 34141 Accepted: 11420 ...
- 点分治——POJ 1741
写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 ...
- POJ 1741 Tree(树的点分治,入门题)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 21357 Accepted: 7006 Description ...
- ●POJ 1741 Tree
题链: http://poj.org/problem?id=1741题解: 树上点分治. 入门题,不多说了. 代码: #include<cstdio> #include<cstrin ...
随机推荐
- [BZOJ 3227] [SDOI 2008] 红黑树(tree)
Description 红黑树是一类特殊的二叉搜索树,其中每个结点被染成红色或黑色.若将二叉搜索树结点中的空指针看作是指向一个空结点,则称这类空结点为二叉搜索树的前端结点.并规定所有前端结点的高度为- ...
- 微信小程序之初探(常见语法 VS vue)常见问题(点击不生效,数据绑定)
最近在调研微信小程序开发,对于一个前端小白来说,在各种框架都还用不熟的情况下,再来开发小程序确实还是不容易. 小程序出来之初,听过演讲,看过一点点儿视频,感觉和angular语法有点相似(PS:那是也 ...
- Curl请求慢
背景原因:测试环境发现一个连接内网访问和外网访问延迟差别很大,内网访问很快.外网访问很慢.于是我们用curl来诊断问题所在的区域! 命令如下: 1 curl -o /dev/null -s -w %{ ...
- pycharm的Database连接新的Mysql5.7报错[08001]
在URL的后面增加参数: ?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC 解决. 原因是虽然mysql5.7的s ...
- windows下网络编程UDP
转载 C++ UDP客户端服务器Socket编程 UDPServer.cpp #include<winsock2.h>#include<stdio.h>#include< ...
- Linux命令_sed
1.替换(将"xxx"替换成"yyy") 现有文件pets.txt 要将其中的"my"替换为"your",可以这样替换, ...
- CH4INRULZ从渗透到提权
下载了镜像后查看了ip http://192.168.16.128/ 然后用nmap扫描了一波 sudo nmap -vv -sV 192.168.16.128 访问80端口发现是个个人博客 访问80 ...
- python 基础部分重点复习整理2
把这里的题目争取刷一遍 博客记录 python的ORM框架peewee SQLAlchemy psycopg2 Django 在1 的基础上,重点突出自己以前没注意的,做到精而不杂!!! Python ...
- ioctl函数
一.函数原型 #include <unistd.h> int ioctl(int fd, int request, .../* void *arg */); 二.和网络相关的请求(requ ...
- #1 macos和windows下对多Python环境配置的记录
为啥会发现环节配置的问题 因为scrapy的setting前期走弯路的时候,碰到了修改了Windows下的Python中的scrapy的默认setting,但是我电脑上还有anaconda,而且我是使 ...