POJ 1741 [点分治][树上路径问题]

时间:2022-09-19 22:14:10
/*
不要低头,不要放弃,不要气馁,不要慌张
题意:
给一棵有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 [点分治][树上路径问题]的更多相关文章

  1. POJ 1741 Tree 求树上路径小于k的点对个数&rpar;

                                                                                                 POJ 174 ...

  2. POJ 1741 树分治

    题目链接[http://poj.org/problem?id=1741] 题意: 给出一颗树,然后寻找点对(u,v)&&dis[u][v] < k的对数. 题解: 这是一个很经典 ...

  3. &lbrack;八分之三的男人&rsqb; POJ - 1741 点分治 &amp&semi;&amp&semi; 点分治笔记

    题意:给出一棵带边权树,询问有多少点对的距离小于等于\(k\) 本题解参考lyd的算法竞赛进阶指南,讲解的十分清晰,比网上那些讲的乱七八糟的好多了 不过写起来还是困难重重(史诗巨作 打完多校更详细做法 ...

  4. POJ 1741 点分治

    方法:指针扫描数组 每次选择树的重心作为树根,从树根出发进行一次DFS,求出点到树根的距离,把节点按照与树根的的距离放进数组d,设置两个指针L,R分别从前.后开始扫描,每次满足条件时答案累加R-L., ...

  5. 【POJ 1741】 Tree &lpar;树的点分治&rpar;

    Tree   Description Give a tree with n vertices,each edge has a length(positive integer less than 100 ...

  6. poj 1741 楼教主男人八题之中的一个:树分治

    http://poj.org/problem? id=1741 Description Give a tree with n vertices,each edge has a length(posit ...

  7. POJ 1741&period;Tree and 洛谷 P4178 Tree-树分治&lpar;点分治,容斥版&rpar; &plus;二分 模板题-区间点对最短距离&lt&semi;&equals;K的点对数量

    POJ 1741. Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 34141   Accepted: 11420 ...

  8. 点分治——POJ 1741

    写的第一道点分治的题目,权当认识点分治了. 点分治,就是对每条过某个点的路径进行考虑,若路径不经过此点,则可以对其子树进行考虑. 具体可以看menci的blog:点分治 来看一道例题:POJ 1741 ...

  9. poj 1741 树的点分治&lpar;入门&rpar;

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 18205   Accepted: 5951 Description ...

随机推荐

  1. iOS 中对 HTTPS 证书链的验证

    这篇文章是我一边学习证书验证一边记录的内容,稍微整理了下,共扯了三部分内容: HTTPS 简要原理: 数字证书的内容.生成及验证: iOS 上对证书链的验证. HTTPS 概要 HTTPS 是运行在 ...

  2. mysql 远程连接失败(linux)

    主要有三个原因:1.mysql授权表里没有远程机器的权限,及需要在授权表mysql.user添加grant all privileges on *.* to 'root'@'远程登陆IP' ident ...

  3. Hadoop基于Protocol Buffer的RPC实现代码分析-Server端

    http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.google.co ...

  4. Xshell不能连接SSH的解决

    异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 重新启动看看:/etc/init.d/ssh restart (/etc/ini ...

  5. BZOJ&lowbar;2152&lowbar;聪聪可可&lowbar;点分治

    BZOJ_2152_聪聪可可_点分治 Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)…… ...

  6. Eclipse设置格式化每行字符的长度

    Windows>>prefrence>>Java>>CodeStyle>>formatter>>edit>>line wrapp ...

  7. cocos2d-x3&period;0 macOS下配置Android开发环境以及使用cocos2d-console来新建执行project

    下面是子龙山人录制的关于cocos2d-x3.0的视频教程,macOS下配置Android开发环境.使用cocos2d-console来新建执行project.怎样执行cocos2d-x 3.0win ...

  8. redhat下安装mysql 5&period;6&period;20&comma;解压zip包,查看已经安装过的mysql&comma;卸载rpm安装包,安装mysqlserver端和client,改动mysqlusername&comma;登陆mysql,启动关闭mysql

     1 将相关的mysql rpm包上传到redhat上 2  我的电脑是Redhat 6.*版本号.所以这里使用上面一个 3  解压zip包 4  安装下面几个rpm MySQL-client-a ...

  9. node 垃圾回收

    一些思考 回收 nodejs垃圾回收 跟浏览器js不同,  以下代码会找出内存泄露 var theThing = null var replaceThing = function () { var o ...

  10. 深入浅出 Java Concurrency &lpar;11&rpar;&colon; 锁机制 part 6 CyclicBarrier

      如果说CountDownLatch是一次性的,那么CyclicBarrier正好可以循环使用.它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).所谓屏障 ...