树上路径!!!点分治处理。(就是在树上分治处理,把树分成小树,再分成更小的树处理)
找最小的满足>=S 并且<=E的路径。
假设从随便一个点开始dfs,复杂度o(n);
然而从重心开始dfs,复杂度为O(logn);
重心:删掉这个点以后,剩余的森林的最大的size最小的点。
注意一下:合并路径时,两条路径不能有相同的祖先(处理某点,路径必须是过这个点,且路径的两端点不在同一棵子树的)。
#include
#include
#include
#include
using namespace std;
int tp, tov[200005], tow[200005], nex[200005], h[100005], n, m, ans = 1e9;
int siz[200005], ma[200005], mama = 1e9, vis[200050],s, e, ss, zong,root,k,zhan[2000005],top;
void read(int &x)
{
x = 0;
int f = 0;
char c = getchar();
while(c < '0' || c > '9')
{
if(c == '-') f = 1;
c = getchar();
}
while(c >= '0' && c <= '9')
{
x = 10 * x + c - '0';
c = getchar();
}
if(f) x = -x;
}
struct node
{
int val, zx;
};
node dis[200005];
bool cmp(const node a,const node b)
{
return a.val < b.val;
}
void add(int x,int y,int w)
{
tp++;
tov[tp] = y;
tow[tp] = w;
nex[tp] = h[x];
h[x] = tp;
}
void getroot(int x,int fa)
{
siz[x] = 1;
ma[x] = 0;
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if(vis[v] || v == fa) continue;
getroot(v,x);
siz[x] += siz[v];
if(siz[v] > ma[x]) ma[x] = siz[v];
}
ma[x] = max(ma[x],zong - siz[x]);
if(ma[x] < mama)
{
root = x;
mama = ma[x];
}
}
void jisuan(int x,int fa,int len,int ha)
{
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if(v == fa || vis[v]) continue;
int made = 0;
if(ha == - 1) made = v;else made = ha;
dis[++s] = (node){len+tow[i],made};
jisuan(v,x,len+tow[i],made);
}
}
void solve(int x,int len)
{
s = 1;
dis[1] = (node){len,0};
jisuan(x,x,len,-1);
sort(dis+1,dis+1+s,cmp);
int l = 1, r = s, temp = 0;
for(int i = 1; i <= s; i++)
{
int pos = lower_bound(dis+1,dis+1+s,(node){ss - dis[i].val,-1},cmp) - dis ;
if(pos < i ) break;
for(int j = pos; j <= s; j++)
{
if(dis[i].val + dis[j].val > e ||dis[i].val + dis[j].val > ans ) break;
if(dis[i].val + dis[j].val >= ss && dis[i].zx != dis[j].zx)
{
ans = min(ans,dis[i].val + dis[j].val );
break;
}
}
}
/* for(int i = 1; i <= s; i++){
int pos = lower_bound(dis + 1, dis + 1 + s, (node) {ss - dis[i].val,-1 },cmp) - dis;
if(pos < i)break;
for( int k = pos; k <= s; k++){
int c = dis[k].val + dis[i].val;
if(c > ans || c > e)break;
if(dis[k].zx == dis[i].zx || c < ss) continue;
ans = min(ans, c); break;
}
}
*/}
void dfs(int x)
{
vis[x] = 1;
solve(x,0);
for(int i = h[x]; i; i = nex[i])
{
int v = tov[i];
if( vis[v]) continue;
zong = siz[v];
mama = 1e9;
getroot(v,v);
dfs(root);
}
}
int main()
{
// freopen("path.in","r",stdin);
// freopen("path.out","w",stdout);
read(n);read(ss);read(e);
for(int i = 1; i <= n - 1; i++)
{
int x,y,w;
read(x);read(y);read(w);
add(x,y,w);
add(y,x,w);
}
mama = 1e9;
memset(vis,0,sizeof(vis));
getroot(1,1);
dfs(root);
if(ans < 1e9)printf("%d",ans);
else printf("-1");
return 0;
}
//其实我并没有想到。dfs暴力60+;