1. 程式人生 > >【JZOJ4715】樹上路徑

【JZOJ4715】樹上路徑

Description

給出一棵樹,求出最小的k,使得,且在樹中存在路徑p,使得k>=S且k<=E。(k為路徑p上的邊的權值和)

題目描述使人神清氣爽。——LYD729

Solution

樹上多條路徑問題顯然用點分治解決。

於是像常規點分治那樣,求出每個點到重心的距離,排序。然後列舉開頭,二分出一個位置使得距離大於等於下界,然後如果這兩個點在同一棵子樹就把二分出的點跳到另一棵子樹上。

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring> #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) #define N 100001 #define M 200001 using namespace std; int p,q; int to[M],next[M],last[M],num=0; int val[M]; int siz[N]; int dis[N]; int fa[N]; int f[N]; bool vis[N]; struct node{ int x,f; }d[N]; int
tot; void link(int x,int y,int c) { num++; to[num]=y; next[num]=last[x]; last[x]=num; val[num]=c; } bool cmp(node x,node y) { return x.x<y.x; } int rt; int cnt=0; void get(int x,int t,int from) { for(int i=last[x];i;i=next[i]) { int v=to[i]; if(v!=t && !vis[v]) { dis[v]=dis[x]+val[i]; get(v,x,from); } } if
(dis[x]) { tot++; d[tot].x=dis[x]; d[tot].f=from; } } void find(int x,int p,int t) { siz[x]=1; f[x]=0; for(int i=last[x];i;i=next[i]) { int v=to[i]; if(v!=t && !vis[v]) { find(v,p,x); siz[x]+=siz[v]; f[x]=max(f[x],siz[v]); } } f[x]=max(f[x],p-siz[x]); if(f[x]<f[rt]) rt=x; } int ans=2147483647; int nx[N]; void calc() { sort(d+1,d+tot+1,cmp); nx[tot]=tot+1; fd(i,tot-1,1) if(d[i].f==d[i+1].f) nx[i]=nx[i+1]; else nx[i]=i+1; if(tot==1 && d[1].x>=p && d[1].x<=q && d[1].x<ans) ans=d[1].x; fo(i,1,tot-1) { if(d[i].x>=p && d[i].x<ans) ans=d[i].x; int l=i+1,r=tot; while(l+1<r) { int mid=(l+r)/2; if(d[i].x+d[mid].x>=p) r=mid; else l=mid; } int t=l; if(d[i].x+d[t].x<p) t++; while(d[i].f==d[t].f) t=nx[t]; if(t>tot) continue; if(d[i].x+d[t].x>=p && d[i].x+d[t].x<=q) { if(ans>d[i].x+d[t].x) ans=d[i].x+d[t].x; } } } void dfs(int x,int t) { vis[x]=true; tot=0; dis[x]=0; for(int i=last[x];i;i=next[i]) { int v=to[i]; if(v!=t && !vis[v]) { dis[v]=val[i]; get(v,x,v); } } calc(); for(int i=last[x];i;i=next[i]) { int v=to[i]; if(!vis[v] && v!=t) { rt=0; find(v,siz[v],x); dfs(rt,x); } } } int main() { int n; cin>>n>>p>>q; fo(i,1,n-1) { int x,y,c; scanf("%d %d %d",&x,&y,&c); link(x,y,c); link(y,x,c); } rt=0; f[0]=2147483647; find(1,n,0); dfs(rt,0); if(ans>q) cout<<-1; else cout<<ans; }