【JZOJ 4715】 树上路径
来源:互联网 发布:dw代码复制到淘宝店铺 编辑:程序博客网 时间:2024/04/26 13:49
Description
给出一棵树,求出最小的k,使得,且在树中存在路径p,使得k>=S且k<=E。(k为路径p上的边的权值和)
对于100%的数据满足n<=10^5,|E-S|<=10^6
对于所有数据满足1<=Wi<=1000,|E|,|S|<=10^9
Analysis
经典的点分治。
具体方法就像树中点对距离一样,记录到重心的距离与所属的子树。
按到重心的距离排序。
一个指针往右扫,二分出另一个最靠左的位置使得dis[l]+dis[pos]>=S,若belong[l]=belong[pos],则使pos跳到其右边的第一个与其不同子树的位置,这个可以预处理。
Code
#include<cstdio>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,b,a) for(int i=b;i>=a;i--)#define efo(i,v) for(int i=last[v];i;i=next[i])using namespace std;const int N=100010,M=N*2,INF=2147483647;int n,num,ans,liml,limr,tot,to[M],next[M],wei[M],last[N];int rt,size[N],right[N];struct node{ int x,s;}a[N];bool bz[N];bool cmp(node a,node b){ return a.x<b.x;}void link(int u,int v,int w){ to[++tot]=v,wei[tot]=w,next[tot]=last[u],last[u]=tot;}void getnum(int v,int fr){ num++; efo(i,v) { int u=to[i]; if(u==fr || bz[u]) continue; getnum(u,v); }}void getrt(int v,int fr){ size[v]=1; efo(i,v) { int u=to[i]; if(u==fr || bz[u]) continue; getrt(u,v); size[v]+=size[u]; } if(size[v]>num-size[v] && !rt) rt=v;}void dfs(int v,int fr,int d,int S){ a[++num].x=d,a[num].s=S; efo(i,v) { int u=to[i]; if(u==fr || bz[u]) continue; dfs(u,v,d+wei[i],S); }}int find(int l,int r,int x){ while(l<r) { int mid=(l+r)>>1; if(x+a[mid].x<liml) l=mid+1; else r=mid; } return l;}void divide(int v,int fr){ num=rt=0; getnum(v,fr); getrt(v,fr); num=0; efo(i,rt) { int u=to[i]; if(u==fr || bz[u]) continue; dfs(u,rt,wei[i],u); } sort(a+1,a+num+1,cmp); fo(i,1,num) if(liml<=a[i].x && a[i].x<=limr) { ans=min(ans,a[i].x); break; } right[num]=num+1; fd(i,num-1,1) if(a[i].s!=a[i+1].s) right[i]=i+1; else right[i]=right[i+1]; fo(i,1,num-1) { int pos=find(i+1,num,a[i].x); if(a[pos].s==a[i].s) pos=right[pos]; if(pos>num) continue; if(liml<=a[i].x+a[pos].x && a[i].x+a[pos].x<=limr) ans=min(ans,a[i].x+a[pos].x); } bz[rt]=1; efo(i,rt) { int u=to[i]; if(u==fr || bz[u]) continue; divide(u,rt); }}int main(){ int u,v,w; scanf("%d %d %d",&n,&liml,&limr); if(liml>limr) { printf("-1"); return 0; } fo(i,1,n-1) { scanf("%d %d %d",&u,&v,&w); link(u,v,w),link(v,u,w); } ans=INF; divide(1,0); if(ans==INF) printf("-1"); else printf("%d",ans); return 0;}
0 0
- 【JZOJ 4715】 树上路径
- 【JZOJ 4715】树上路径
- JZOJ 4715 树上路径 (点分)
- JZOJ.4715【NOIP2016提高A组模拟8.19】树上路径
- JZOJ 4715 【NOIP2016提高A组模拟8.19】树上路径
- JZOJ 4757 树上摩托
- 树上路径
- 树上路径
- 树上路径
- jzoj 4715. 【NOIP2016提高A组模拟8.19】树上路径 点分治
- jzoj 5055. 【GDOI2017模拟二试4.12】树上路径 点分治
- noip2013truck树上路径倍增
- 树上的路径
- [bzoj3784]树上的路径
- 树上最长单色路径
- 树上最长单色路径
- 树上最长单色路径
- 3784: 树上的路径
- SurfaceView详细解析
- 安卓 service
- vijos1426兴奋剂检查(多维费用的背包问题+状态压缩+hash)
- java基础学习之事件监听--鼠标点击
- ListView+头部向上滑动标题栏渐显以及ScrollView向上滑动标题栏渐显
- 【JZOJ 4715】 树上路径
- 面试题16:反转链表(java)
- Adapter模式(适配器模式 结构型)
- SpringMVC从数据库中读取图片显示到JSP页面上
- dfs
- GeekBand C++ STL与泛型编程 第六周笔记
- kaggle实例学习-Titanic(4)
- oracle的分页
- NPOI插入行