P5836 [USACO19DEC] Milk Visits S
P5836 [USACO19DEC] Milk Visits S
题目翻译:
给出一棵树,求任意两点间的唯一路径上是否有\(G\)或\(H\)
思路:
这是一道\(LCA\)的变形,这一次要维护的是路径上有的点。令\(f[u][i][0]\)为\(u\)节点的\(2^i\)次父亲节点。\(f[u][i][1]\)为其\(2^i\)次父亲节点的奶牛是否有\(G\),同理\(f[u][i][2]\)为其\(2^i\)次父亲节点的奶牛是否有\(H\)。因此我们只需要维护这三个值,最后求\(lca\)时判断即可
完整代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int>e[N];
int f[N][32][3],dep[N];
int op[N];
void dfs(int u,int fa){
dep[u]=dep[fa]+1;
f[u][0][0]=fa;
f[u][0][1]=(op[u]==1)||(op[fa]==1);
f[u][0][2]=(op[u]==2)||(op[fa]==2);
for(int i=1;i<=30;i++){
f[u][i][0]=f[f[u][i-1][0]][i-1][0];
f[u][i][1]=(f[u][i-1][1])||(f[f[u][i-1][0]][i-1][1]);
f[u][i][2]=(f[u][i-1][2])||(f[f[u][i-1][0]][i-1][2]);
}
for(auto ed:e[u]){
if(ed==fa)continue;
dfs(ed,u);
}
}
int lca(int x,int y,int opt){
if(dep[x]<dep[y])swap(x,y);
for(int i=30;i>=0;i--){
if(dep[f[x][i][0]]<dep[y])continue;
if(f[x][i][opt])return 1;
x=f[x][i][0];
}
if(x==y){
if(op[x]==opt)return 1;
else return 0;
}
for(int i=30;i>=0;i--){
if(f[x][i][0]==f[y][i][0])continue;
if(f[x][i][opt] || f[y][i][opt])return 1;
x=f[x][i][0];
y=f[y][i][0];
}
if(f[x][0][opt] || f[y][0][opt])return 1;
return 0;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
char opt;
cin>>opt;
op[i]=(opt=='G'?1:2);
}
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
while(m--){
int u,v;
char opt;
cin>>u>>v>>opt;
cout<<lca(u,v,(opt=='G'?1:2));
}
}
最近公共祖先讲解
本文作者:XichenOC
本文链接:https://www.cnblogs.com/XichenOC/p/18682382
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步