(这次的英文题面要比上一个容易看多了)
(英语蒟蒻的卑微)
又是一个很裸的LCA题
(显然,这次不太容易打暴力咧)
(但听说还是有大佬用dfs直接a掉了)
正好
趁这个机会复习一下LCA
这里用的是倍增lca
的思想(一不小心是会写tle的吧)
(也有可能是因为我太弱了才t掉的)
我才不会说我有一次卑微了
一开始看PPT
以为自己明白了
结果发现
有一点点问题
由于本题中这个树是题里给的
所以节点的编号不可以简简单单认为是从上到下从左到右顺序排列的
(但其实这部算什么大问题啊qwq)
(还是我太弱了)
长记性了的我这次记住了要加'\n'
#include<cstdio> #include<iostream> #include<cstring> #define maxn 40000 using namespace std; struct EDGE { int nxt,to,v; }edge[maxn*2+5]; int T,n,root,cnt,m; int head[maxn+5],dep[maxn+5],dis[maxn+5]; int f[maxn+5][25]; bool vis[maxn+5]; void add(int x,int y,int z) { edge[++cnt].to=y; edge[cnt].v=z; edge[cnt].nxt=head[x]; head[x]=cnt; } void dfs(int u,int fa) { dep[u]=dep[fa]+1; for(int i=0; i<=22; i++) { f[u][i+1]=f[f[u][i]][i]; } for(int i=head[u]; i; i=edge[i].nxt) { if(edge[i].to==fa) { continue; } dis[edge[i].to]=dis[u]+edge[i].v; f[edge[i].to][0]=u; dfs(edge[i].to,u); } } int LCA(int x,int y) { if(dep[x]<dep[y]) { swap(x,y); } for(int i=22; i>=0; i--) { if(dep[f[x][i]]>=dep[y]) { x=f[x][i]; } if(x==y) { return x; } } for(int i=22; i>=0; i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } int main() { scanf("%d",&T); while(T--) { memset(vis,0,sizeof(vis)); memset(edge,0,sizeof(edge)); memset(f,0,sizeof(f)); memset(dep,0,sizeof(dep)); memset(head,0,sizeof(head)); memset(dis,0,sizeof(dis)); cnt=0; scanf("%d%d",&n,&m); for(int i=1; i<=n-1; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); vis[y]=1; add(x,y,z); add(y,x,z); } for(int i=1; i<=n; i++) { if(vis[i]==0) { root=i; break; } } dfs(root,0); for(int i=1; i<=m; i++) { int a,b; scanf("%d%d",&a,&b); printf("%d\n",dis[a]+dis[b]-2*dis[LCA(a,b)]); } } return 0; }