POJ 1741 点分治
方法:指针扫描数组
每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前、后开始扫描,每次满足条件时答案累加R-L。,之后减去子树的满足条件的情况,删除根节点,对其子树继续上述操作,不断累加答案。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100010;
vector<pair<int,int> >G[maxn];
int d[maxn],size[maxn],root,max_w,n1,cnt,n,k;
bool vis[maxn];
void get_root(int x,int f){//求树的重心
size[x]=1;
int max_part=0;
for(int i=0;i<G[x].size();i++){
int Next=G[x][i].first;
if(Next!=f&&!vis[Next]){
get_root(Next,x);
size[x]+=size[Next];
max_part=max(max_part,size[Next]);
}
}
max_part=max(max_part,n1-size[x]);
if(max_part<max_w){
root=x;
max_w=max_part;
}
}
void get_dist(int x,int f,int dist){//算距离
d[++cnt]=dist;
size[x]=1;//算距离的同时也更新一下子树的大小
for(int i=0;i<G[x].size();i++){
int Next=G[x][i].first;
if(Next!=f&&!vis[Next]){
get_dist(Next,x,dist+G[x][i].second);
size[x]+=size[Next];
}
}
}
int cal(int x,int y){//计算
cnt=0;
get_dist(x,-1,y);
sort(d+1,d+1+cnt);
int ans=0;
for(int i=1,j=cnt;i<j;i++){
while(d[i]+d[j]>k&&i<j)j--;
ans+=j-i;
}
return ans;
}
int dfs(int x){//dfs主框架
max_w=n1;
get_root(x,-1);
int now=root;
vis[now]=1;
int ans=0;
ans+=cal(now,0);
for(int i=0;i<G[now].size();i++){
int Next=G[now][i].first;
if(!vis[Next]){
ans-=cal(Next,G[now][i].second);
n1=size[Next];
ans+=dfs(Next);
}
}
return ans;
}
void init(int n){
for(int i=1;i<=n;i++)G[i].clear();
cnt=0;
memset(vis,0,sizeof(vis));
}
int main(){
int u,v,dis;
while(~scanf("%d%d",&n,&k)&&n&&k){
init(n);
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&dis);
G[u].push_back(make_pair(v,dis));
G[v].push_back(make_pair(u,dis));
}
n1=n;
printf("%d\n",dfs(1));
}
}
//5 1
//1 2 1
//2 3 1
//3 4 1
//4 5 1
POJ 1741 点分治的更多相关文章
- POJ 1741 树分治
题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...
- POJ 1741 [点分治][树上路径问题]
/* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给一棵有n个节点的树,每条边都有一个正权值,求一共有多少个点对使得它们之间路的权值和小于给定的k. 思路: <分治算法在树的路径问题中的应用 ...
- [八分之三的男人] POJ - 1741 点分治 && 点分治笔记
题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...
- 【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(树的点分治)
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.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 ...
随机推荐
- 算法练习2---斐波那契数列java版
古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子, 假如兔子都不死,问每个月的兔子总数为多少? 数列:1 1 2 3 5 8 ...
- eclipse部署和启动guns
eclipse部署guns: 1.import -> 搜索maven -> Existing Maven Projects -> 选择guns根目录 2.修改配置文件: spring ...
- linux进程学习-创建新进程
init进程将系统启动后,init将成为此后所有进程的祖先,此后的进程都是直接或间接从init进程“复制”而来.完成该“复制”功能的函数有fork()和clone()等. 一个进程(父进程)调用for ...
- LeetCode Relative Ranks
原题链接在这里:https://leetcode.com/problems/relative-ranks/#/description 题目: Given scores of N athletes, f ...
- [ Laravel 5.5 文档 ] 处理用户请求 —— HTTP 请求的过滤器:中间件
[ Laravel 5.5 文档 ] 处理用户请求 —— HTTP 请求的过滤器:中间件 http://laravelacademy.org/post/7812.html 简介 中间件为过滤进入应用的 ...
- unity3d___UGui中如何创建loading...进度条
http://blog.sina.com.cn/s/blog_e82e8c390102wh2z.html 实现方法:通过Image组件中Image Type属性中Fill Amount,通过代码改变F ...
- Linux下markdown编辑软件 — retext 支持实时预览,存为pdf、html、ODT等
本文由Suzzz原创,发布于 http://www.cnblogs.com/Suzzz/p/4129368.html,转载请保留此声明 ReText是一个linux下的markdown和reStruc ...
- linux user date
useradd username 添加用户 userdel username 删除用户 passwd username 设置用户密码 passwd 设置当前用户密码 passwd -d usernam ...
- MySQL insert插入
使用INSERT语句插入新数据 语法:INSERT [INTO] tbl_name [(col_name,...)] VALUES (pression,...),… INSERT [INTO ...
- Java基础--阻塞队列ArrayBlockingQueue
ArrayBlockingQueue是阻塞队列的一种,基于数组实现,长度固定,队尾添加,队首获取, 构造函数: ArrayBlockingQueue(int capacity) ArrayBlocki ...