1. 程式人生 > >[USACO08OCT]牧場散步Pasture Walking (LCA) (亂搞)

[USACO08OCT]牧場散步Pasture Walking (LCA) (亂搞)

getchar() 亂搞 body usaco next show org clas bits

題面傳送門我太懶了所以吃掉題面

題解

可以發現如果兩點不在一條鏈上的話,那麽他們的最短路徑一定會經過LCA。

所以可以維護一下每個點到樹根的距離,然後大力前綴和亂搞就好了。

#include <bits/stdc++.h>

const int max_n=1e4+5;

int N,M,cnt;
int depth[max_n],father[15][max_n],lg2[max_n],first_edge[max_n],dis[max_n];

struct edge
{
    int to,w,next_edge;
}linker[max_n<<1];

inline
int read() { register int x=0; register char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) { x=(x<<1)+(x<<3)+ch-‘0‘; ch=getchar(); } return x; } inline void add_edge(int x,int y,int z) { linker[++cnt].to=y; linker[cnt].w=z; linker[cnt].next_edge=first_edge[x]; first_edge[x]=cnt; return
; } inline void LCA_init(int cur,int fa) { depth[cur]=depth[fa]+1; father[0][cur]=fa; for(register int i=1;i<=lg2[depth[cur]];++i) father[i][cur]=father[i-1][father[i-1][cur]]; for(register int k=first_edge[cur];k;k=linker[k].next_edge) { if(!depth[linker[k].to]) { dis[linker[k].to]=dis[cur]+linker[k].w; LCA_init(linker[k].to,cur); } } return
; } inline int LCA(int x,int y) { if(depth[x]<depth[y]) std::swap(x,y); while(depth[x]>depth[y]) x=father[lg2[depth[x]-depth[y]]][x]; if(x==y) return x; for(register int i=lg2[depth[x]];i>=0;--i) if(father[i][x]!=father[i][y]) x=father[i][x],y=father[i][y]; return father[0][x]; } int main() { int x,y,z; N=read(),M=read(); lg2[0]=-1; for(register int i=1;i<N;++i) { x=read(),y=read(),z=read(); add_edge(x,y,z),add_edge(y,x,z); lg2[i]=lg2[i>>1]+1; } lg2[N]=lg2[N>>1]+1; LCA_init(1,0); for(register int i=1;i<=M;++i) { x=read(),y=read(); printf("%d\n",dis[x]+dis[y]-(dis[LCA(x,y)]<<1)); } return 0; }

博主是蒟蒻,有錯誤請指出,謝謝!

[USACO08OCT]牧場散步Pasture Walking (LCA) (亂搞)