【BZOJ】1468: Tree(POJ1741)

【题意】给定带边权树,求两点距离<=k的点对数。n<=40000。

【算法】点分治

【题解】对于一个区域,选择其重心x作为根,则划分出来的每棵子树都是子区域,可以证明至多划分log n次(通过vis[]划分区域)。每次划分所有点都扫描一次,所以仅遍历的复杂度是O(n log n)。

对于本题,将点x的所有子树节点dis处理出来后排序,然后用双指针法易得<=k的点对数。

但是,这样会把来自同一子树的路径也计算进去,需要减去。来自同一子树y的距离<=k的路径的数量等同于子树y内路径的距离+2*w<=k的路径的数量。

所以,设dis[y]=w后再减去子树y的路径数即可。

具体做法:calc(x,0)表示dis[x]=0统计得到的子树x内<=k的路径数,则ans(x)=calc(x,0)-calc(y,w),y=son[x],w是边(x,y)的权值。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=50010;
ll ans;
int root,first[maxn],tot,cnt,sz[maxn],sum,d[maxn],k,n;
bool vis[maxn];
struct edge{int v,w,from;}e[maxn*2];
void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
void getroot(int x,int fa){
    sz[x]=1;
    bool ok=1;
    for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v]){
        getroot(e[i].v,x);
        sz[x]+=sz[e[i].v];
        if(sz[e[i].v]>sum/2)ok=0;
    }
    if(sum-sz[x]<=sum/2&&ok)root=x;
}
void getdeep(int x,int fa,int w){
    d[++cnt]=w;
    for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&!vis[e[i].v])getdeep(e[i].v,x,w+e[i].w);
}
ll calc(int x,int w){
    cnt=0;getdeep(x,0,w);
    sort(d+1,d+cnt+1);
    int l=1,r=cnt;
    ll sum=0;
    while(l<r){
        if(d[l]+d[r]<=k){sum+=r-l;l++;}
        else r--;
    }
    return sum;
}
void solve(int x,int s){
    ans+=calc(x,0);vis[x]=1;
    for(int i=first[x];i;i=e[i].from)if(!vis[e[i].v]){
        ans-=calc(e[i].v,e[i].w);
        if(sz[e[i].v]>sz[x])sum=s-sz[x];else sum=sz[e[i].v];
        getroot(e[i].v,x);
        solve(root,sum);
    }
}
int main(){
    scanf("%d",&n);
    int u,v,w;
    for(int i=1;i<n;i++){
        scanf("%d%d%d",&u,&v,&w);
        insert(u,v,w);insert(v,u,w);
    }
    scanf("%d",&k);
    sum=n;
    getroot(1,0);
    ans=0;
    solve(root,n);
    printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/onioncyc/p/7067414.html

时间: 2024-11-09 16:21:44

【BZOJ】1468: Tree(POJ1741)的相关文章

【BZOJ】1468: Tree(点分治)

http://www.lydsy.com/JudgeOnline/problem.php?id=1468 分治真是一门高大上的东西... 好神... 树分治最好资料是:qzc的<分治算法在树的路径问题中的应用> 我来说说自己的理解: 点分=找重心+分治 找重心尤为重要,因为这关系到时间复杂度. 对于递归式 $$T(n)=aT(n/b)+O(D(n))$$ 这类递归式,如果能保证每一层都是$O(D(n))$,那么时间复杂度会大大减小.(详见算导第三章和第四章) 对于一棵树,如果我们在找到重心后,

【3】Decision tree(决策树)

前言 Decision tree is one of the most popular classification tools 它用一个训练数据集学到一个映射,该映射以未知类别的新实例作为输入,输出对这个实例类别的预测. 决策树相当于将一系列问题组织成树,具体说,每个问题对应一个属性,根据属性值来生成判断分支,一直到决策树的叶节点就产生了类别. 那么,接下来的问题就是怎么选择最佳的属性作为当前的判断分支,这就引出了用信息论划分数据集的方式. 在信息论中,划分数据之前和之后信息发生的信息变化成为

【转】Device Tree(三):代码分析

原文网址:http://www.wowotech.net/linux_kenrel/dt-code-analysis.html 一.前言 Device Tree总共有三篇,分别是: 1.为何要引入Device Tree,这个机制是用来解决什么问题的?(请参考引入Device Tree的原因) 2.Device Tree的基础概念(请参考DT基础概念) 3.ARM linux中和Device Tree相关的代码分析(这是本文的主题) 本文主要内容是:以Device Tree相关的数据流分析为索引,

【leetcode】Same Tree(easy)

Given two binary trees, write a function to check if they are equal or not. Two binary trees are considered equal if they are structurally identical and the nodes have the same value. 思路:太简单! bool isSameTree(TreeNode *p, TreeNode *q) { if(p == NULL &

Android自定义组件系列【5】——进阶实践(1)

简介 项目开发中发现问题.解决问题这个过程中会出现很多问题,比如重复出现.某个问题的遗留,这些问题的本质就是设计模式.今天记录设计模式的知识点. 内容 在java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖.关联.聚合.组合.继承.实现.它们的耦合度依次增强. 依赖关系:对于两个相对独立的对象,当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系.关联关系:分为单向关联和双向关联.在java中,单向关联表现为:类A当中使用了

【BZOJ2998】Problem A(动态规划)

[BZOJ2998]Problem A(动态规划) 题面 BZOJ 题解 一个人的成绩范围可以确定为一个区间 这样就变成了 选择若干区间,不重合, 每个区间有个权值,求最大权值和 这样就可直接\(dp\)了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #includ

【BZOJ3566】概率充电器(动态规划)

[BZOJ3566]概率充电器(动态规划) 题面 BZOJ Description 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: "采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生活不可或缺的必需品!能充上电吗?现在就试试看吧! " SHOI 概率充电器由 n-1 条导线连通了 n 个充电元件.进行充电时,每条导线是否可以导电以概率决定,每一个充电元件自身是否直接进行充电也由概率决定. 随后电能可以从直

【Chrome】Chrome插件开发(一)插件的简单实现

不同浏览器插件开发比较 Chrome的插件开发起来最简单,总体上看没什么新的技术,开发语言就是javascript,web前端工程师能很快上手. Firefox的插件开发则复杂许多,涉及到环境的搭建和一些WEB以外的技术. IE的插件开发就更复杂了,需要熟悉C++和COM技术,当然还要装微软的Visual Studio. 这里有篇老外写的文章,对比Chrome.Opera和Firefox的插件开发的:http://blog.nparashuram.com/2011/10/writing-brow

【TYVJ】1307 联络员(最小生成树)

http://tyvj.cn/Problem_Show.aspx?id=1307 kruskal裸题.(水题红色警报) #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> using namespace std; #define rep(i, n) for(int