POJ 1741 [点分治][树上路径问题]
/*
不要低头,不要放弃,不要气馁,不要慌张
题意:
给一棵有n个节点的树,每条边都有一个正权值,求一共有多少个点对使得它们之间路的权值和小于给定的k.
思路:
《分治算法在树的路径问题中的应用》
*/ #include<stdio.h>
#include<vector>
#include<string.h>
#include<algorithm>
#define N 10050
using namespace std;
struct edge{
int id;
long long w;
bool im;
edge *next;
};
struct st{
st(){}
st(int a,long long b,int c){
id=a;dis=b;iid=c;
}
int id,iid;
long long dis;
};
vector<st>mv;
edge edges[N*];
edge *adj[N];
long long ans,kk;
int ednum;
inline void addedge(int a,int b,long long c){
edge *tmp=&edges[ednum++];
tmp->id=b;
tmp->w=c;
tmp->im=;
tmp->next=adj[a];
adj[a]=tmp;
}
int zong,next_val,next;
bool vis[N];
int siz[N],fa[N];
long long dis[N];
void dfs(int pos,int dep){
vis[pos]=;
siz[pos]=;
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
dfs(it->id,dep+);
siz[pos]+=siz[it->id];
}
}
}
void dfs2(int pos,int dep){
int my_next=-;
vis[pos]=;
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
my_next=max(my_next,siz[it->id]);
}
}
my_next=max(my_next,zong-siz[pos]);
if(next_val>my_next){
next=pos;
next_val=my_next;
}
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
dfs2(it->id,dep+);
}
}
}
bool cmp1(st a,st b){
if(a.dis!=b.dis)return a.dis<b.dis;
else return a.iid<b.iid;
}
bool cmp2(st a,st b){
if(a.id!=b.id)return a.id<b.id;
else if(a.dis!=b.dis)return a.dis<b.dis;
else return a.iid<b.iid;
}
inline void del(int a,int b){
for(edge *it=adj[a];it;it=it->next){
if(it->id==b){
it->im=;
return;
}
}
}
void dfs3(int pos,int dep){
vis[pos]=;
if(!dep)dis[pos]=;
for(edge *it=adj[pos];it;it=it->next){
if(it->im&&!vis[it->id]){
if(!dep)fa[it->id]=it->id;
else fa[it->id]=fa[pos];
dis[it->id]=dis[pos]+it->w;
mv.push_back(st(fa[it->id],dis[it->id],it->id));
dfs3(it->id,dep+);
}
}
}
void solve(int pos){
mv.clear();
memset(vis,,sizeof(vis));
dfs(pos,);
zong=siz[pos];
if(zong<=)return;
memset(vis,,sizeof(vis));
next_val=;
dfs2(pos,);
memset(vis,,sizeof(vis));
dfs3(next,);
int n=mv.size();
sort(mv.begin(),mv.end(),cmp1);
for(int i=;i<n;i++){
if(mv[i].dis>kk)break;
ans++;
int l=i+,r=n-;
while(l<=r){
int mid=(l+r)>>;
if(mv[i].dis+mv[mid].dis<=kk)l=mid+;
else r=mid-;
}
ans+=r-i;
}
sort(mv.begin(),mv.end(),cmp2);
int st=;
for(int i=;i<n;i++){
if(mv[i].id!=mv[st].id){
for(int j=st;j<i;j++){
int l=j+,r=i-;
while(l<=r){
int mid=(l+r)>>;
if(mv[j].dis+mv[mid].dis<=kk)l=mid+;
else r=mid-;
}
ans-=r-j;
}
st=i;
}
}
for(int j=st;j<n;j++){
int l=j+,r=n-;
while(l<=r){
int mid=(l+r)>>;
if(mv[j].dis+mv[mid].dis<=kk)l=mid+;
else r=mid-;
}
ans-=r-j;
}
vector<int>mmv;
for(edge *it=adj[next];it;it=it->next){
if(it->im&&siz[it->id]>){
mmv.push_back(it->id);
it->im=;
del(it->id,next);
}
}
for(int i=;i<mmv.size();i++)solve(mmv[i]);
}
int main()
{
int n;
while(scanf("%d%lld",&n,&kk)!=EOF){
ans=;
if(!n)break;
memset(adj,NULL,sizeof(adj));
ednum=;
for(int i=;i<n;i++){
int a,b;
long long c;
scanf("%d%d%lld",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
solve();
printf("%lld\n",ans);
}
}
POJ 1741 [点分治][树上路径问题]的更多相关文章
- POJ 1741 Tree 求树上路径小于k的点对个数)
POJ 174 ...
- POJ 1741 树分治
题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...
- [八分之三的男人] POJ - 1741 点分治 && 点分治笔记
题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...
- POJ 1741 点分治
方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...
- 【POJ 1741】 Tree (树的点分治)
Tree Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...
- 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 ...
- poj 1741 树的点分治(入门)
Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 18205 Accepted: 5951 Description ...
随机推荐
- 0x00到0xFF二进制数值中1的的个数
似乎有点无聊耶~~~~~(>_<)~~~~ #include <stdio.h> , , , , , , , , , , , , , , , }; ] = { , , , , ...
- python 抓取百度音乐
# coding:utf-8 import urllib2 import re import urllib import chardet from json import * category = ' ...
- Navicat premium工具常用快捷键
Navicat premium是一款数据库管理工具,它可以以单一程式同时连线到MySQL.PostgreSQL. Oracle .SQL Server 及 SQLite 资料库,让管理不同类型的资料库 ...
- 如何换ionic里面的图标
(转自http://www.zcool.com.cn/article/ZMTM4NDQw.html) 第一步,你把你的项目的SVG文件跟你自己做的图标的SVG文件都上到icomoon.io/app(上 ...
- jQuery的选择器中的通配符使用介绍
$("input[id^='data']");//id属性以data开始的所有input标签 $("input[id$='data']");//id属性以dat ...
- html页面元素事件丢失
前段时间做网站包括最近用mvc做oa都发现这个奇怪现象,就是页面加载完毕后页面元素事件(比如按钮点击.复选框change)一切正常,但是当执行查询或者其他操作后页面事件丢失.具体原因暂没有时间分析,现 ...
- 自己瞎捣腾的Win7下Linux安装之路-----图例篇
写在前面 网上很多这方面的教程,我也是参考他们的文章和一些书籍才弄成功.没啥创新性,只为记录下来,以供自已理解和以后复习. 所谓工欲善其事,必先利其器.俺想学习Linux,当然是要先装一个Linux( ...
- 享元模式(Flyweight Pattern)
一.引言 在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非 ...
- [BCB] C++ BUILDER 绘图 随机生成图形
由于老师要求要实现一个填充算法,而每次填充都需要一个源图形[不规则],用mspaint自己画太麻烦,于是打算自己动手随机生成. 这里用的是 Polygen()函数,但是注意首尾相接,另外,为了保证规则 ...
- 原生js发送ajax请求
堕落了一阵子了,今天打开博客,发现连登录的用户名和密码都不记得了.2016年已过半,不能再这么晃荡下去了. 参加了网易微专业-前端攻城狮 培训,目前进行到大作业开发阶段,感觉举步维艰.但是无论如何,不 ...