• 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
    ",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
  • 相关阅读:
    [Leetcode] Median of Two Sorted Arrays
    [Jobdu] 题目1463:招聘会
    [Leetcode] Merge Two Sorted Lists
    [Leetcode] Combinations
    [Leetcode] Populating Next Right Pointers in Each Node II
    [Leetcode] Insertion Sort List
    redis在Web中的使用
    设计模式:单例模式
    设计模式:基本法则
    设计模式:工厂模式
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10193660.html
Copyright © 2020-2023  润新知