BOJ

BOJ 13306 - 트리

playdeom 2024. 4. 18. 21:47

그냥 문제가 너무 길다. 

 

문제를 요약하자면 모든 정점들이 어느 한 정점으로 연결되어 있는 트리가 있고 두가지 쿼리가 주어진다.

1. 두 정점의 간선을 끊는다

2. 선택한 정점과 연결된 정점들의 개수를 센다.

 

일반적인 방법으로는 문제를 해결하기에는 어려워보인다.

1번 쿼리는 n-1개 들어오기 때문에 최종 상태에서는 모든 정점들이 서로 연결되어 있지 않음을 알 수 있다.

그러면 여기서 쿼리를 거꾸로 수행해보고 싶은 생각이 들 수 있다.

간선을 끊는 쿼리를 구현하는 것은 어려우므로 쿼리를 거꾸로 실행하게 되면 간선을 추가하는 쿼리로 바뀌게 된다!

여기서 바로 유니온 파인드를 사용할 수 있다.

1번 쿼리가 들어오면 두 정점을 유니온 하고 2번 쿼리가 들어오면 연결된 정점들의 개수를 세어주기만 하면 된다.

정점들의 개수는 루트 노드가 되는 정점에 정보를 저장한다. 

 

오프라인 쿼리를 구성하는 방법을 연습하기 좋은 문제였다.

 

더보기
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <ext/rope>
#include <cassert>
#include <x86intrin.h>
using namespace std;
using namespace __gnu_cxx;

// utils
#define fastio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define endl "\n"
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define repair(x) x.erase(unique(all(x)),x.end())
typedef long long ll; //long long. or use int64_t
typedef long double ld; //long double
const int iinf = 1e9; //integer maximum
const long long linf = 1e18; //long long maximum
const int mod = 1e9 + 7; //prime number

// gcd, lcm, egcd funcs
template<class T>T gcd(T x, T y){if (!y)return x;return gcd(y,x%y);}
template<class T>T lcm(T x, T y){return (x*y)/gcd(x,y);}
template<class T>tuple<T,T,T> egcd(T a, T b){
	if(b==0)return {a,1,0};
	auto[g,x,y]=egcd(b,a%b);
	return {g,y,x-(a/b)*y};
}
// builtin funcs
template<class T>T bitcnt(T x){return __builtin_popcount(x);}
template<class T>T bitpar(T x){return __builtin_parity(x);}
template<class T>T bitclz(T x){return __builtin_clz(x);}
template<class T>T bitctz(T x){return __builtin_ctz(x);}
// debuging funcs
#define deb(x) cout<<#x<<": "<<(x)<<endl
//////////////////////////////////////////
struct ds{
	vector<int>par;
	int n;
	ds(int N){
		n=N;
		par.resize(n);
		iota(all(par),0);
	}
	int find(int x){
		if(x==par[x])return x;
		return par[x]=find(par[x]);
	}
	void uni(int x, int y){
		x=find(x);y=find(y);
		par[x]=y;
	}
};
int main(){
	fastio;
	int n,q;
	cin>>n>>q;
	vector<int>arr(n+1);
	for(int i=2; i<=n; i++)cin>>arr[i];
	ds dst(n+1);
	q+=n-1;
	vector<tuple<int,int,int>>query;
	int a,b,c=-1;
	while(q--){
		cin>>a;
		if(a==0)cin>>b;
		else cin>>b>>c;
		query.push_back({a,b,c});
		c=-1;
	}
	reverse(all(query));
	vector<string>ans;
	for(auto[a,b,c]:query){
		if(a==0)dst.uni(b,arr[b]);
		else{
			if(dst.find(b)==dst.find(c))ans.push_back("YES");
			else ans.push_back("NO");
		}
	}
	reverse(all(ans));
	for(auto&v:ans)cout<<v<<endl;
	return 0;
}

 

'BOJ' 카테고리의 다른 글

BOJ 28068 - I Am Knowledge  (0) 2024.05.08
BOJ 30108 - 교육적인 트리 문제  (0) 2024.04.26
BOJ 20194 - 경계 로봇  (2) 2024.01.31
BOJ 17433 - 신비로운 수  (0) 2024.01.27
BOJ 1437 - 수 분해  (0) 2024.01.23