题意:
勇气小镇是一个有着n个房屋的小镇,为什么把它叫做勇气小镇呢,这个故事就要从勇气小镇成立的那天说起了,
修建小镇的时候,为了让小镇有特色,镇长特地只修了n-1条路,并且规定说,所有在勇气小镇的村民,每一次出门必须规划好路线,
路线必须满足在到达终点之前绝对不走回头路。每个人都要这样,不然那个人就不配在小镇生活下去,因为他没有这个勇气。
事实上,这并不能算一项挑战,因为n-1条路已经连通了每户人家,不回头地从起点到终点,只是一个时间上的问题。
由于小镇上的福利特别好,所以小懒入住了这个小镇,他规划了m次的行程,每次从L房屋到R房屋,他想问你他每次从L房屋到R房屋最少能走多少路。
题解:
倍增LCA求树上最短路,这颗树是带边权的树,所以需要加一个数组。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=1e5+10; int head[maxn]; int tol; int N,M; struct node { int u; int v; int w; int next; }edge[maxn]; void addedge (int u,int v,int w) { edge[tol].u=u; edge[tol].v=v; edge[tol].w=w; edge[tol].next=head[u]; head[u]=tol++; } //lca int father[20][maxn]; int h[maxn]; int d[maxn]; void dfs (int x) { for (int i=head[x];i!=-1;i=edge[i].next) { int v=edge[i].v; if (v==father[0][x]) continue; father[0][v]=x; h[v]=h[x]+1; d[v]=d[x]+edge[i].w; dfs(v); } } int lca (int x,int y) { if (h[x]<h[y]) swap(x,y); for (int i=17;i>=0;i--) if (h[x]-h[y]>>i) x=father[i][x]; if (x==y) return x; for (int i=17;i>=0;i--) { if (father[i][x]!=father[i][y]) { x=father[i][x]; y=father[i][y]; } } return father[0][x]; } int getDis (int x,int y) { return d[x]+d[y]-d[lca(x,y)]*2; } int main () { int T; scanf("%d",&T); while (T--) { scanf("%d%d",&N,&M); memset(head,-1,sizeof(head)); memset(father,0,sizeof(father)); memset(h,0,sizeof(h)); memset(d,0,sizeof(d)); tol=0; for (int i=0;i<N-1;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } dfs(1); for (int i=1;i<=17;i++) for (int j=1;j<=N;j++) father[i][j]=father[i-1][father[i-1][j]]; for (int i=0;i<M;i++) { int u,v; scanf("%d%d",&u,&v); printf("%d ",getDis(u,v)); } } return 0; }