树上的路径
来源:互联网 发布:如何改变图片尺寸软件 编辑:程序博客网 时间:2024/03/29 14:55
树上的路径
时间限制: 1 Sec 内存限制: 256 MB
题目描述
给定一棵N个结点的树,结点用正整数1..N编号,每条边有一个正整数权值。用d(a,b)表示从结点a到结点b路径上经过边的权值和,其中要求a
题解
类似于noi2009超级钢琴的做法,先用点分治找出每个点能和它联通的点的区间,然后把这些东西扔到一个堆里,用主席树维护区间第K大即可。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<queue>#include<algorithm> #define N 50010#define inf 1050000000using namespace std;int n,m,cnt,size[N],w[N],fa[N],dis[N],s[N*17],c[N*17];int k,la[N],ff[N*2],q[N],flag[N],st,maxn,tot;struct node{int a,b,c;}map[N*2];struct wbs{ int l,r,pos,num1,num2; bool operator<(const wbs &cyc) const{return num1+num2<cyc.num1+cyc.num2;}};struct point{int lc,rc,size;}t[N*270];priority_queue<wbs>h;void add(int a,int b,int c){ map[++k]=(node){a,b,c};ff[k]=la[a];la[a]=k; map[++k]=(node){b,a,c};ff[k]=la[b];la[b]=k;}int find(int S){ int l=1,r=2,num=inf,res;q[1]=S;flag[S]=1;fa[S]=0; while(l<r) { int x=q[l];l++;size[x]=1;w[x]=0; for(int a=la[x];a;a=ff[a]) if(!flag[map[a].b]) q[r]=map[a].b,flag[q[r]]=1,fa[q[r]]=x,r++; } if(r==2)return -1; for(int i=r-1;i;i--) { int x=q[i];flag[x]=0; if(fa[x])size[fa[x]]+=size[x],w[fa[x]]=max(w[fa[x]],size[x]); if(max(w[x],r-size[x]-1)<num)num=max(w[x],r-size[x]-1),res=x; } return res;}void work(int S,int top,int num){ int l=1,r=2,end=cnt,tmp=0; q[1]=S;dis[S]=num;flag[S]=1; while(l<r) { int x=q[l];l++;s[++cnt]=dis[x];tmp=max(tmp,dis[x]); for(int a=la[x];a;a=ff[a]) if(!flag[map[a].b]) q[r]=map[a].b,flag[q[r]]=1,dis[q[r]]=dis[x]+map[a].c,r++; } for(int i=r-1;i;i--) { int x=q[i];flag[x]=0; h.push((wbs){st,end,end-st+1,dis[x],maxn}); } maxn=max(maxn,tmp);}void solve(int x){ int rt=find(x); if(rt==-1)return; flag[rt]=1;st=++cnt;maxn=0;s[cnt]=0; for(int a=la[rt];a;a=ff[a]) if(!flag[map[a].b])work(map[a].b,rt,map[a].c); for(int a=la[rt];a;a=ff[a]) if(!flag[map[a].b])solve(map[a].b);}class seg_tree{ public: void modify(int x,int pre,int l,int r,int des) { t[x]=t[pre];t[x].size++; if(l==r)return; int mid=l+r>>1; if(des<=mid)modify(t[x].lc=++tot,t[pre].lc,l,mid,des); else modify(t[x].rc=++tot,t[pre].rc,mid+1,r,des); } int qry(int x,int pre,int l,int r,int des) { if(l==r)return c[l]; int mid=l+r>>1,num=t[t[x].lc].size-t[t[pre].lc].size; if(des<=num)qry(t[x].lc,t[pre].lc,l,mid,des); else qry(t[x].rc,t[pre].rc,mid+1,r,des-num); }}T;int main(){ int a,b,v; scanf("%d%d",&n,&m); for(int i=1;i<n;i++) scanf("%d%d%d",&a,&b,&v),add(a,b,v); solve(1); for(int i=1;i<=cnt;i++)c[i]=s[i]; sort(c+1,c+cnt+1);tot=cnt; int Tnum=unique(c+1,c+cnt+1)-c-1; for(int i=1;i<=cnt;i++) T.modify(i,i-1,1,Tnum,lower_bound(c+1,c+Tnum+1,s[i])-c); while(m--&&h.size()) { wbs x=h.top();h.pop(); printf("%d\n",x.num1+x.num2); if(x.pos==1)continue; x.num2=T.qry(x.r,x.l-1,1,Tnum,--x.pos); h.push(x); } return 0;}
0 0
- 树上的路径
- [bzoj3784]树上的路径
- 3784: 树上的路径
- 【bzoj3784】树上的路径
- bzoj 3784: 树上的路径
- Codevs 2756 树上的路径
- 树上路径
- 树上路径
- 树上路径
- 【CODE[VS]】2756 树上的路径
- [bzoj3784][点分治]树上的路径
- noip2013truck树上路径倍增
- 树上最长单色路径
- 树上最长单色路径
- 树上最长单色路径
- 【JZOJ 4715】 树上路径
- 【JZOJ4715】树上路径
- 【JZOJ 4715】树上路径
- Servlet实现文件上传,可多文件上传
- 原来软件工程可以这样学~~~
- C/C++指针和引用详解
- MySQL 如何实现行转列分级输出?
- Java并发提纲
- 树上的路径
- 线程安全和线程不安全
- Java中改变应用程序界面外观(javax.swing.UIManager类和LookAndFeel类)
- 数据结构实践项目——最短路径和拓扑序列
- css不定宽度居中
- 利用xtrabackupex在线添加slave-MHA
- 大小之差
- ServletContext学习总结
- android侧滑菜单功能代码