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; }