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
1 2 1
1 3 2
2 4 3
2 5 4
Sample Output
7
7
6
5
4
4
3
3
2
1
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
- bzoj 3784: 树上的路径
- BZOJ 3784|树上的路径|点分治|堆|RMQ
- [BZOJ 3784][树上的路径][点分治+堆]
- 3784: 树上的路径
- [可持久化可并堆 || ST表 点分治] BZOJ 3784 树上的路径
- bzoj 3784: 树上的路径 (ST表+优先队列+点分治)
- 【BZOJ 3697】采药人的路径 树上点分治
- 树上的路径
- [bzoj3784]树上的路径
- 【bzoj3784】树上的路径
- bzoj 1906: 树上的蚂蚁
- Codevs 2756 树上的路径
- 【BZOJ 1316】 树上的询问 树分治
- BZOJ 1316: 树上的询问 点分治
- 树上路径
- 树上路径
- 树上路径
- 【CODE[VS]】2756 树上的路径
- 正则表达式验证身份证
- 第十六题(接口)
- 在使用事务尾部日志备份时报错‘由于在请求 'COMPRESSION' 之前使用不兼容的结构格式化了介质’
- Android中处理加载图片时内存溢出问题
- android AsyncTask异步任务
- bzoj 3784: 树上的路径
- TSH Pass
- 在Android上使用ZXing识别条形码/二维码(转)
- code first 数据库创建更新
- C++作业4.17与4.18合成版
- 第三方应用分享到微信朋友圈功能
- 分布式模式之Broker模式
- 第十五题(泛型)
- 注释