【CODECHEF】Children Trips

题意

 

 

 

 

 题解

先看一下 https://www.cnblogs.com/yoyoball/p/9397857.html

这里说个坑点

在跳的时候,可能会遇到这种情况

 

 假设求的是3->4,体力为2

3,4跳一次只能到2号点

所以加起来要两次,然而你发现只要一次就够了

所以在跳的时候只能跳到lca以下,然后看剩下的距离加起来要一次还是两次

代码

#include<algorithm>
#include<iostream>
#include<vector>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 100010
int dep[N],ans[N],up[N][21],up2[N][21],lev[N];
struct Query
{
	int a,b,p,id;
}q[N];
struct line
{
	int ed,cost;
};
vector<line> vec[N];
bool operator <(Query a,Query b)
{
	return a.p<b.p;
}
int get_lca(int x,int y)
{
    if(lev[x]<lev[y]) swap(x,y);
    for(int i=20;lev[x]>lev[y];i--)
    {
        if(lev[up[x][i]]>=lev[y]) x=up[x][i];
    }
    if(x==y) return x;
    for(int i=20;up[x][0]!=up[y][0];i--)
    {
        if(up[x][i]!=up[y][i])
        {
            x=up[x][i];
            y=up[y][i];
        }
    }
    return up[x][0];
}
int jump_once(int id,int p)
{
	int ret=id;
	for(int i=20;i>=0;i--)
	{
		if(dep[id]-dep[up[ret][i]]<=p) ret=up[ret][i];
	}
	return ret;
}
int jump(int a,int p,int lca,int &tot)//use by q[i].p>=len
{
	if(a==lca) return a;
	while(true)
	{
		int t=jump_once(a,p);
		if(lev[t]>lev[lca]) a=t,tot++;
		else return a;
	}
}
int jump2(int a,int lca,int &tot)//use by q[i].p<len
{
	if(a==lca) return a;
	for(int i=20;i>=0;i--)
	{
		if(lev[up2[a][i]]>lev[lca])
			a=up2[a][i],tot+=(1<<i);
	}
	return a;
}
void dfs(int id,int from,int p) 
{
    if(!p)
	{
		up[id][0]=from;
    	for(int i=1;i<=20;i++) up[id][i]=up[up[id][i-1]][i-1];
    	lev[id]=lev[from]+1;
	}
	else
	{
		up2[id][0]=jump_once(id,p);
		for(int i=1;i<=20;i++) up2[id][i]=up2[up2[id][i-1]][i-1];
	}
    for(int i=0;i<vec[id].size();i++)
    {
        line l=vec[id][i];
        if(l.ed==from) continue;
		dep[l.ed]=dep[id]+l.cost;
        dfs(l.ed,id,p);
    }
}
int main()
{
	int n,m,len;
	cin>>n;
	len=sqrt(n);
	for(int i=1;i<n;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		vec[a].push_back((line){b,c});
		vec[b].push_back((line){a,c});
	}
	dfs(1,0,0);
	cin>>m;
	for(int i=1;i<=m;i++) scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].p),q[i].id=i;
	sort(q+1,q+1+m);
	for(int i=1;i<=m;i++)
	{
		int lca=get_lca(q[i].a,q[i].b);
		if(q[i].p<len)
		{
			if(q[i].p!=q[i-1].p) dfs(1,0,q[i].p);
			q[i].a=jump2(q[i].a,lca,ans[q[i].id]);
			q[i].b=jump2(q[i].b,lca,ans[q[i].id]);			
		}
		else
		{
			q[i].a=jump(q[i].a,q[i].p,lca,ans[q[i].id]);
			q[i].b=jump(q[i].b,q[i].p,lca,ans[q[i].id]);
		}
		int dis=dep[q[i].a]+dep[q[i].b]-dep[lca]*2;
		ans[q[i].id]+=(dis>q[i].p?2:1)-(dis==0);
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}

  

 

posted @ 2020-05-27 13:05  linzhuohang  阅读(223)  评论(0编辑  收藏  举报