[BZOJ 1468][POJ 1741]Tree

Posted trisolaris

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 1468][POJ 1741]Tree相关的知识,希望对你有一定的参考价值。

[BZOJ 1468][POJ 1741]Tree

 

<题意概括>

给定一棵树,求有多少对满足两两距离不超过k的点对(u,v)

 

<做法>

典型的点分治题目

找出当前树的重心

计算该顶点到其子树中每个顶点的路径长度

使用双指针法统计满足条件的路径条数并减去那些在同一棵子树中的路径

删除该顶点并递归处理每一棵子树

 

<Code> 

技术分享图片
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Fast register
#define INF 2147483647
inline int Max(const int&x,const int&y){return x>y?x:y;}

inline char Getchar(){
    static char BUF[16384],*S=BUF,*T=BUF;
    return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++;
}
inline int Getint(){
    Fast int s=0;Fast char c=Getchar();
    while(c<48||c>57)c=Getchar();
    while(c>47&&c<58)s=s*10+c-48,c=Getchar();
    return s;
}

struct Edge{
    int to,v;Edge*next;
    Edge(const int&T,const int&V,Edge*&N):to(T),v(V),next(N){}
}*Front[40001];
#define AddEdge(x,y,z) Front[x]=new Edge(y,z,Front[x])
int root;
int Size[40001];
int MaxSize[40001];
int Recent_Node;
bool vis[40001];
int Distance[40001];
int Dis[40001];
int Cnt_Dis;
int N,DisLimit;
int Ans;

inline void FindBarycenter(const int&now,const int&Fa){
    Size[now]=1;MaxSize[now]=0;
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(o->to!=Fa&&!vis[o->to]){
            FindBarycenter(o->to,now);
            Size[now]+=Size[o->to];
            MaxSize[now]=Max(MaxSize[now],Size[o->to]);
        }
    }
    MaxSize[now]=Max(MaxSize[now],Recent_Node-Size[now]);
    if(MaxSize[now]<MaxSize[root])root=now;
}
inline void Cal_Dis(const int&now,const int&Fa){
    Dis[++Cnt_Dis]=Distance[now];
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(o->to!=Fa&&!vis[o->to]){
            Distance[o->to]=Distance[now]+o->v;
            Cal_Dis(o->to,now);
        }
    }
}
inline int Calculate(const int&now,const int&DisNow){
    Distance[now]=DisNow,Cnt_Dis=0;
    Cal_Dis(now,0);
    std::sort(Dis+1,Dis+Cnt_Dis+1);
    Fast int L=1,R=Cnt_Dis,Num=0;
    while(L<R)Dis[L]+Dis[R]<=DisLimit?Num+=R-L,++L:--R;
    return Num;
}
inline void Slove(const int&now){
    Ans+=Calculate(now,0),vis[now]=true;
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(!vis[o->to]){
            Ans-=Calculate(o->to,o->v);
            root=0;
            Recent_Node=Size[o->to];
            FindBarycenter(o->to,now);
            Slove(root);
        }
    }
}
int main(){
    N=Getint();
    for(Fast int i=1;i<N;++i){
        Fast int u=Getint(),v=Getint(),l=Getint();
        AddEdge(u,v,l);AddEdge(v,u,l);
    }
    DisLimit=Getint();
    MaxSize[root=0]=INF;
    Recent_Node=N;
    FindBarycenter(1,0);
    Slove(root);
    printf("%d\n",Ans);
    return 0;
}
[BZOJ 1468]Tree 
技术分享图片
#include<cstdio>
#include<cstring>
#include<algorithm>
#define Fast register
#define INF 2147483647
inline int Max(const int&x,const int&y){return x>y?x:y;}

inline char Getchar(){
    static char BUF[16384],*S=BUF,*T=BUF;
    return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++;
}
inline int Getint(){
    Fast int s=0;Fast char c=Getchar();
    while(c<48||c>57)c=Getchar();
    while(c>47&&c<58)s=s*10+c-48,c=Getchar();
    return s;
}

struct Edge{
    int to,v;Edge*next;
    Edge(const int&T,const int&V,Edge*&N):to(T),v(V),next(N){}
}*Front[10001];
#define AddEdge(x,y,z) Front[x]=new Edge(y,z,Front[x])
int root;
int Size[10001];
int MaxSize[10001];
int Recent_Node;
bool vis[10001];
int Distance[10001];
int Dis[10001];
int Cnt_Dis;
int N,DisLimit;
int Ans;

inline void FindBarycenter(const int&now,const int&Fa){
    Size[now]=1;MaxSize[now]=0;
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(o->to!=Fa&&!vis[o->to]){
            FindBarycenter(o->to,now);
            Size[now]+=Size[o->to];
            MaxSize[now]=Max(MaxSize[now],Size[o->to]);
        }
    }
    MaxSize[now]=Max(MaxSize[now],Recent_Node-Size[now]);
    if(MaxSize[now]<MaxSize[root])root=now;
}
inline void Cal_Dis(const int&now,const int&Fa){
    Dis[++Cnt_Dis]=Distance[now];
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(o->to!=Fa&&!vis[o->to]){
            Distance[o->to]=Distance[now]+o->v;
            Cal_Dis(o->to,now);
        }
    }
}
inline int Calculate(const int&now,const int&DisNow){
    Distance[now]=DisNow,Cnt_Dis=0;
    Cal_Dis(now,0);
    std::sort(Dis+1,Dis+Cnt_Dis+1);
    Fast int L=1,R=Cnt_Dis,Num=0;
    while(L<R)Dis[L]+Dis[R]<=DisLimit?Num+=R-L,++L:--R;
    return Num;
}
inline void Slove(const int&now){
    Ans+=Calculate(now,0);vis[now]=true;
    for(Fast Edge*o=Front[now];o!=NULL;o=o->next){
        if(!vis[o->to]){
            Ans-=Calculate(o->to,o->v);
            root=0;
            Recent_Node=Size[o->to];
            FindBarycenter(o->to,now);
            Slove(root);
        }
    }
}
int main(){
    while(N=Getint(),DisLimit=Getint(),N||DisLimit){
        Recent_Node=N;
        memset(Front,NULL,sizeof Front);
        memset(vis,false,sizeof vis);
        for(Fast int i=1;i<N;++i){
            Fast int u=Getint(),v=Getint(),l=Getint();
            AddEdge(u,v,l);AddEdge(v,u,l);
        }
        MaxSize[Ans=root=0]=INF;
        FindBarycenter(1,0);
        Slove(root);
        printf("%d\n",Ans);
    }
    return 0;
}
[POJ 1741]Tree 

以上是关于[BZOJ 1468][POJ 1741]Tree的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1468: Tree(POJ1741)

BZOJ.1468.Tree(点分治)

BZOJ 1468: Tree

poj1741 Tree

[bzoj 1468] Tree

[BZOJ1468]Tree