2018.12.28-bzoj-3784-树上的路径

题目描述:

给定一个N个结点的树,结点用正整数1..N编号。每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路边上经过边的权值。其中要求a<b.将这n*(n-1)/2个距离从大到小排序,输出前M个距离值。

算法标签:点分治,st表

思路:

处理出点分治序后,思路跟超级钢琴是相同的,对于每一条链,确定可以与我连成一条路径的点,在点分治序上的区间,用优先队列处理每一个最大值不断二分,得到前m大

以下代码:

#include<bits/stdc++.h>
#define il inline
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=5e4+5,M=1e6;
struct node{int l,r,pos,v,b;bool operator<(const node&t1)const{return v<t1.v;};};
int n,m,head[N],ne[N<<1],to[N<<1],cnt,w[N<<1];priority_queue<node> q;
int rt,sz[N],son[N],size,mx[M][20],L,R,m1,m2,dist[M],Lg[M];bool vis[N];
il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;w[cnt]=z;}
il int Max(int x,int y){return dist[x]>dist[y]?x:y;}
il void getrt(int x,int fa){
    sz[x]=1;son[x]=0;
    for(int i=head[x];i;i=ne[i]){
        if(fa==to[i]||vis[to[i]])continue;
        getrt(to[i],x);sz[x]+=sz[to[i]];
        son[x]=max(son[x],sz[to[i]]);
    }
    son[x]=max(son[x],size-sz[x]);
    if(son[rt]>son[x])rt=x;
}
il void dfs(int x,int fa,int v){
    mx[++cnt][0]=cnt;dist[cnt]=v;
    if(dist[m2]<v)m2=cnt;
    q.push((node){L,R,m1,v+dist[m1],v});
    for(int i=head[x];i;i=ne[i])
        if(fa!=to[i]&&!vis[to[i]])dfs(to[i],x,v+w[i]);
}
il void solve(int x){
    vis[x]=1;L=++cnt;m1=cnt;
    mx[cnt][0]=cnt;dist[cnt]=0;
    for(int i=head[x];i;i=ne[i]){
        if(vis[to[i]])continue;
        m2=0;R=cnt;dfs(to[i],x,w[i]);
        m1=dist[m1]>dist[m2]?m1:m2;
    }
    for(int i=head[x];i;i=ne[i]){
        if(vis[to[i]])continue;
        rt=0;size=sz[to[i]];
        getrt(to[i],x);solve(rt);
    }
}
il void init(){
    for(int i=2;i<=cnt;i++)Lg[i]=Lg[i>>1]+1;
    for(int j=1;j<=Lg[cnt];j++)for(int i=1;i+(1<<j-1)<=cnt;i++)
        mx[i][j]=Max(mx[i][j-1],mx[i+(1<<j-1)][j-1]);
}
il int query(int l,int r){
    int k=Lg[r-l+1];
    return Max(mx[l][k],mx[r-(1<<k)+1][k]);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<n;i++){int x=read(),y=read(),z=read();insert(x,y,z);insert(y,x,z);}
    cnt=0;son[0]=n;size=n;getrt(1,0);solve(rt);
    init();
    while(m--){
        node now=q.top();q.pop();int p;printf("%d\n",now.v);
        if(now.l<now.pos)p=query(now.l,now.pos-1),q.push((node){now.l,now.pos-1,p,dist[p]+now.b,now.b});
        if(now.pos<now.r)p=query(now.pos+1,now.r),q.push((node){now.pos+1,now.r,p,dist[p]+now.b,now.b});
    }
    return 0;
}
View Code

 

posted @ 2018-12-29 07:53  Jessiejzy  阅读(163)  评论(0编辑  收藏  举报