树上的路径
树上的路径
题目描述
给定一棵N个结点的树,结点用正整数1..N编号,每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路径上经过边的权值和,其中要求a<b。将这N*(N-1)/2个距离值从大到小排序,输出前M个距离值。
Sol
今天见识了一种高级东东:点分治序。
就是每次点分dfs是,同时记一个dfs序,一个点可以对应多个不同的dfs序。
考虑原先点分合并时是一棵棵子树合并上去,现在改成一个点对应一段dfs序的区间,表示这个点的链可以和这个区间合并。
然后我们把点和区间放进堆里,每次取堆顶,并把堆顶分裂成两个区间。
这个东西似乎很厉害。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #define maxn 50005 9 using namespace std; 10 int n,m,head[maxn],tot; 11 int siz,f[maxn],sc,rt,vis[maxn],sz[maxn],st[maxn*20][22],w[maxn*20]; 12 int L[maxn*20]; 13 struct node{ 14 int v,nex,w; 15 }e[maxn*2]; 16 struct no{ 17 int l,r,x,v; 18 }; 19 bool operator <(no a,no b){ 20 return a.v<b.v; 21 } 22 priority_queue<no>q; 23 void add(int t1,int t2,int t3){ 24 e[++tot].v=t2;e[tot].w=t3;e[tot].nex=head[t1];head[t1]=tot; 25 } 26 void findr(int k,int fa){ 27 f[k]=0;sz[k]=1; 28 for(int i=head[k];i;i=e[i].nex){ 29 if(e[i].v==fa||vis[e[i].v])continue; 30 findr(e[i].v,k); 31 sz[k]+=sz[e[i].v]; 32 f[k]=max(f[k],sz[e[i].v]); 33 } 34 f[k]=max(f[k],siz-sz[k]); 35 if(f[k]<f[rt])rt=k; 36 } 37 int dfs(int k,int fa,int W,int l,int r,int wm){ 38 sc++;w[sc]=W;st[sc][0]=sc;sz[k]=1; 39 if(l<=r)q.push((no){l,r,sc,W+wm}); 40 int M=W; 41 for(int i=head[k];i;i=e[i].nex){ 42 if(e[i].v==fa||vis[e[i].v])continue; 43 M=max(M,dfs(e[i].v,k,W+e[i].w,l,r,wm)); 44 sz[k]+=sz[e[i].v]; 45 } 46 return M; 47 } 48 void work(int k){ 49 vis[k]=1;int la=sc+1,lw=0; 50 for(int i=head[k];i;i=e[i].nex){ 51 if(vis[e[i].v])continue; 52 int W=dfs(e[i].v,k,e[i].w,la,sc,lw); 53 lw=max(lw,W); 54 } 55 sc++;w[sc]=0;st[sc][0]=sc; 56 if(la<sc)q.push((no){la,sc-1,sc,lw}); 57 for(int i=head[k];i;i=e[i].nex){ 58 if(vis[e[i].v])continue; 59 rt=0;siz=sz[e[i].v];findr(e[i].v,k); 60 work(rt); 61 } 62 } 63 int ask(int l,int r){ 64 int t=L[r-l+1]; 65 int a=st[l][t],b=st[r-(1<<t)+1][t]; 66 return w[a]>w[b]?a:b; 67 } 68 int main() 69 { 70 cin>>n>>m; 71 for(int i=1,t1,t2,t3;i<n;i++){ 72 scanf("%d%d%d",&t1,&t2,&t3); 73 add(t1,t2,t3);add(t2,t1,t3); 74 } 75 rt=0;f[0]=1e9;siz=n;findr(1,0); 76 work(rt); 77 for(int j=1;j<=20;j++) 78 for(int i=1;i+(1<<j)-1<=sc;i++){ 79 int a=st[i][j-1],b=st[i+(1<<j-1)][j-1]; 80 st[i][j]=(w[a]>w[b])?a:b; 81 } 82 for(int i=2;i<=sc;i++)L[i]=L[i/2]+1; 83 while(m--){ 84 no t=q.top();q.pop(); 85 printf("%d\n",t.v); 86 int p=ask(t.l,t.r); 87 if(p>t.l)q.push((no){t.l,p-1,t.x,w[t.x]+w[ask(t.l,p-1)]}); 88 if(p<t.r)q.push((no){p+1,t.r,t.x,w[t.x]+w[ask(p+1,t.r)]}); 89 } 90 return 0; 91 }