【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]); }
看都看了,顺手点个推荐呗 :)