当前位置: 代码迷 >> 综合 >> codevs 2370小机房的树
  详细解决方案

codevs 2370小机房的树

热度:19   发布时间:2023-10-29 18:09:23.0

先找到他们的最近公共祖先,记下他们的深度(就是花费)
最后的最小花费就是询问的减祖先加起来

#include<cstdio>
#include<iostream>
using namespace std;
const int M=1001009;
int n,m,s,f[M],vis[M],lca[M*2];int nex[M*2],head[M*2],to[M*2],tot,heade[M*2],nexe[M*2],toe[M*2],tote,cos[M*2],x[M],y[M],dep[M];
void add(int x,int y,int z){nex[++tot]=head[x];to[tot]=y;cos[tot]=z;head[x]=tot;
}
void adde(int x,int y){nexe[++tote]=heade[x];toe[tote]=y;heade[x]=tote;
}
int find(int x){return f[x]==x?x:find(f[x]);
}
void dfs(int x){f[x]=x;vis[x]=1;for(int i=head[x];i;i=nex[i]){int tmp=to[i];if(!vis[tmp]){dep[tmp]=dep[x]+cos[i];dfs(tmp);f[tmp]=x;}}for(int i=heade[x];i;i=nexe[i]){int tmp=toe[i];if(vis[tmp]){lca[i]=find(tmp);if(i%2) lca[i+1]=lca[i];else lca[i-1]=lca[i];}}
}
int main(){scanf("%d",&n);for(int i=1;i<n;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z);add(y,x,z);}scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d%d",&x[i],&y[i]);adde(x[i],y[i]);adde(y[i],x[i]);}dfs(1);for(int i=1;i<=m;i++){printf("%d\n",-2*dep[lca[i*2]]+dep[x[i]]+dep[y[i]]);}}