bzoj 3784: 树上的路径

来源:互联网 发布:有没有抢秒杀软件 编辑:程序博客网 时间:2024/04/29 19:05

Description

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

Input

第一行两个正整数N,M
下面N-1行,每行三个正整数a,b,c(a,b<=N,C<=10000)。表示结点a到结点b有一条权值为c的边。

Output

共M行,如题所述.

Sample Input

5 10
1 2 1
1 3 2
2 4 3
2 5 4

Sample Output

7
7
6
5
4
4
3
3
2
1

HINT

N<=50000,M<=Min(300000,n*(n-1) /2 )


做法同NOI2010超级钢琴。很神奇的做法

我们做树分治的时候维护单条链的长度和可以和哪些链连接起来([L,R]区间)

然后用堆维护五元组(s,l,r,d,x)表示(当前段,可以到达的区间的左端点,可以到达的区间右端点,最大值的位置,最大值的ans)

然后最大值用线段树或者ST表维护下都可以

推荐ST表虽然我写的是线段树

#include<queue>#include<vector>#include<cstdio>#include<algorithm>using namespace std;struct line{     int s,t;     int x;     int next;}a[100001];int head[50001];int edge;inline void add(int s,int t,int x){     a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;     a[edge].x=x;}struct tree{     int l,r;     int loc;     int m;}tr[4000001];int s[500001];inline void up(int p){     if(tr[p*2].m>tr[p*2+1].m)     {          tr[p].m=tr[p*2].m;          tr[p].loc=tr[p*2].loc;     }     else     {          tr[p].m=tr[p*2+1].m;          tr[p].loc=tr[p*2+1].loc;     }}inline void build(int p,int l,int r){     tr[p].l=l;     tr[p].r=r;     if(l!=r)     {          int mid=(l+r)/2;          build(p*2,l,mid);          build(p*2+1,mid+1,r);          up(p);     }     else     {          tr[p].m=s[l];          tr[p].loc=l;     }}tree nw;inline tree ask(int p,int l,int r){     if(l<=tr[p].l&&tr[p].r<=r)          return tr[p];     else     {          int mid=(tr[p].l+tr[p].r)/2;          tree ans1=nw,ans2=nw,as=nw;          bool flag1=false,flag2=false;          if(l<=mid)          {               flag1=true;               ans1=ask(p*2,l,r);          }          if(r>mid)          {             flag2=true;               ans2=ask(p*2+1,l,r);          }          if(flag1)          {               if(flag2)               {                    if(ans1.m>ans2.m)                    {                         as.m=ans1.m;                         as.loc=ans1.loc;                    }                    else                    {                         as.m=ans2.m;                         as.loc=ans2.loc;                    }               }               else                    as=ans1;          }          else               as=ans2;          return as;     }}int son[50001],mson[50001];bool v[50001];int mini,minx;int dis[50001];int fa[50001];inline void getroot(int d,int s){ son[d]=0; mson[d]=0;     int i;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(!v[t]&&t!=fa[d])          {             fa[t]=d;             getroot(t,s);               son[d]+=son[t]+1;               mson[d]=max(mson[d],son[t]+1);          }     }     int temp=max(mson[d],s-mson[d]-1);     if(mson[d]<minx)     {          minx=temp;          mini=d;     }}int p;inline void dfs(int d){     int i;     for(i=head[d];i!=0;i=a[i].next)     {         int t=a[i].t;         if(!v[t]&&t!=fa[d])         {           fa[t]=d;           dis[t]=dis[d]+a[i].x;           p++;           s[p]=dis[t];              dfs(t);         }     }}struct gets{     int l,r;}px[1000001];inline void solve(int d){ v[d]=true;     int i,j;     int pp=p;     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(!v[t])          {               dis[t]=a[i].x;               int p1=p;               p++;               s[p]=dis[t];               fa[t]=0;               dfs(t);               for(j=p1+1;j<=p;j++)               {                    px[j].l=pp+1;                    px[j].r=p1;               }          }     }     for(i=head[d];i!=0;i=a[i].next)     {          int t=a[i].t;          if(!v[t])          {               minx=2100000000;               mini=0;               fa[t]=0;               getroot(t,son[d]);               solve(mini);          }      }}struct findx{ int s; int d;     int l,r;     long long x;     bool operator <(findx y) const     {          return x<y.x;     }};priority_queue <findx> Q;int main(){// freopen("path.in","r",stdin);// freopen("path.out","w",stdout);     int n,m;     scanf("%d%d",&n,&m);     int i,ss,tt,x;     for(i=1;i<=n-1;i++)     {          scanf("%d%d%d",&ss,&tt,&x);          edge++;          add(ss,tt,x);          edge++;          add(tt,ss,x);     }     minx=2100000000;     mini=0;     getroot(1,n);     solve(mini);     build(1,1,p);     for(i=1;i<=p;i++)     {          int ss=px[i].l,tt=px[i].r;          if(ss>tt)               continue;          tree x=ask(1,ss,tt);          findx t;          t.s=i;          t.d=x.loc;          t.l=ss;          t.r=tt;          t.x=x.m+s[t.s];          Q.push(t);     }     for(i=1;i<=p;i++)     {          findx t;          t.s=i;          t.d=i;          t.l=i;          t.r=i;          t.x=s[i];          Q.push(t);     }     while(m>0)     {          m--;          findx t=Q.top();          printf("%d\n",t.x);          Q.pop();          tree x;          findx t1,t2;          if(t.d-1>=t.l)          {               x=ask(1,t.l,t.d-1);               t1.s=t.s;               t1.d=x.loc;               t1.l=t.l;               t1.r=t.d-1;               t1.x=x.m+s[t.s];               Q.push(t1);          }          if(t.d+1<=t.r)          {               x=ask(1,t.d+1,t.r);               t2.s=t.s;               t2.d=x.loc;               t2.l=t.d+1;               t2.r=t.r;               t2.x=x.m+s[t.s];               Q.push(t2);          }     }     return 0;}


0 0
原创粉丝点击