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;
}