[ABC295G] Minimum Reachable City
[ABC295G] Minimum Reachable City
Description
给定一张点数为 \(N\) 的有向图,初始 \(p_i(1\leq p_i \leq i,1 \leq i < N)\) 连向 \(i+1\)。
\(Q\) 次操作,有两种:
- 1 u v
:\(u\) 向 \(v\) 连一条有向边,保证最开始时 \(v\) 能到达 \(u\),\(u \ne v\)。
- 2 x
:询问 \(x\) 能到达的点中编号最小的点。
Solutions
-
操作一可以看作 \(u \to v\) 路径上所有点向 \(v\) 连边,我们可以优化为每个点向父节点连边。
-
操作二相当于从 \(x\) 出发,沿我们添加的边向上走到最高点。
我们考虑使用并查集实现,操作一暴力跳就可以。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int n,q,op,u,v;
int p[N],f[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
void merge(int x,int y){
x=find(x);y=find(y);
if(x==y) return;
f[y]=x;
}
int main(){
scanf("%d",&n);
for(int i=2;i<=n;++i) scanf("%d",&p[i]);
for(int i=1;i<=n;++i) f[i]=i;
scanf("%d",&q);
while(q--){
scanf("%d",&op);
if(op==1){
scanf("%d%d",&u,&v);
u=find(u);
while(u>v){
merge(p[u],u);u=find(u);
}
}
else scanf("%d",&u),printf("%d\n",find(u));
}
return 0;
}