【点分治】BZOJ 1468:Tree

来源:互联网 发布:微商造假软件 编辑:程序博客网 时间:2024/06/10 03:56

BZOJ 1468:Tree


Description

给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K


Input

N 接下来n-1行边描述管道,按照题目中写的输入 接下来是k


Output

一行,有多少对点之间的距离小于等于k


Sample Input

7
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10


Sample Output

5


HINT

n<=40000


Solution

每次把root为根所有子树节点的距离dis算出来
然后答案就是把所有子树节点的距离dis排序然后cal得到ans1
然后每个子树所有点再分别cal一次
以root为根的答案就是ans1-ans2
把所有这些加起来即可
吓死我了开始看了一遍查出好多错...果然模板以后还是自己打比较好

Code

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define maxn 400001using namespace std;struct edge{    int to,lst,c;}e[maxn*2];int last[maxn],tot,son[maxn],n,f[maxn],root,d[maxn],deep[maxn],K,sum;bool vis[maxn];void getroot(int poi,int lst){    son[poi]=1;f[poi]=0;     for(int i=last[poi];i;i=e[i].lst)        if(e[i].to!=lst && !vis[e[i].to])        {            getroot(e[i].to,poi);            son[poi]+=son[e[i].to];            f[poi]=max(f[poi],son[e[i].to]);        }    f[poi]=max(f[poi],n-son[poi]);    if(f[root]>f[poi])root=poi;} void getdeep(int poi,int lst){    deep[++deep[0]]=d[poi];    for(int i=last[poi];i;i=e[i].lst)        if(e[i].to!=lst && !vis[e[i].to])        {            d[e[i].to]=d[poi]+e[i].c;            getdeep(e[i].to,poi);        }}int getsum(int poi,int now){    d[poi]=now;deep[0]=0;    getdeep(poi,0);    sort(1+deep,1+deep+deep[0]);    int t=0,l,r;    for(int l=1,r=deep[0];l<r;)    {        if(deep[l]+deep[r]<=K)t+=r-l,l++;        else r--;    }    return t;}void solve(int poi){    vis[poi]=1;    sum+=getsum(poi,0);    for(int i=last[poi];i;i=e[i].lst)        if(!vis[e[i].to])        {            sum-=getsum(e[i].to,e[i].c);            n=son[e[i].to];            root=0;            getroot(e[i].to,poi);            solve(root);        }}void add(int u,int v,int c){    e[++tot]=(edge){v,last[u],c};last[u]=tot;    e[++tot]=(edge){u,last[v],c};last[v]=tot;} int main() {    int k,m;    scanf("%d",&n);    for(int i=1;i<n;i++)    {        int u,v,c;        scanf("%d%d%d",&u,&v,&c);        add(u,v,c);    }    f[root]=100000;    scanf("%d",&K);    getroot(1,0);    solve(root);    printf("%d",sum);    return 0;}
0 0
原创粉丝点击