标签:dep dist fa int t1 Courses CF770C LCA return
有一棵 \(n\) 个节点的树,一共 \(q\) 次询问,每次询问给定 \(3\) 个点,求两条起点终点在这三个点上且不完全重合的路径的最多公共节点数。
Solution
枚举公共点,答案为 \((dis(a,b) + dis(a,c) - dis(b,c)) / 2 + 1\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int n,q,t1,t2,t3;
vector <int> g[N];
int dep[N],fa[N][20],vis[N];
void dfs(int p) {
vis[p]=1;
for(int q:g[p]) {
if(vis[q]) continue;
dep[q]=dep[p]+1;
fa[q][0]=p;
dfs(q);
}
}
int lca(int p,int q) {
if(dep[p]<dep[q]) swap(p,q);
for(int i=18;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
for(int i=18;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i], q=fa[q][i];
if(p-q) return fa[p][0];
return p;
}
int dist(int p,int q) {
int l=lca(p,q);
return dep[p]+dep[q]-2*dep[l];
}
int calc(int a,int b,int c) {
return (dist(a,b)+dist(a,c)-dist(b,c))/2;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>q;
for(int i=1;i<n;i++) {
cin>>t1;
g[i+1].push_back(t1);
g[t1].push_back(i+1);
}
dep[1]=1;
dfs(1);
for(int i=1;i<=18;i++) {
for(int j=1;j<=n;j++) {
fa[j][i]=fa[fa[j][i-1]][i-1];
}
}
for(int i=1;i<=q;i++) {
cin>>t1>>t2>>t3;
cout<<max(max(calc(t1,t2,t3),calc(t2,t3,t1)),calc(t3,t1,t2))+1<<endl;
}
}
标签:dep,dist,fa,int,t1,Courses,CF770C,LCA,return 来源: https://www.cnblogs.com/mollnn/p/12588947.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。