전공/알고리즘

백준 4256(트리)

xkdlaldfjtnl 2020. 6. 30. 17:09

https://www.acmicpc.net/problem/4256

 

4256번: 트리

문제 이진 트리는 매우 중요한 기본 자료 구조이다. 아래 그림은 루트 노드가 유일한 이진 트리이다. 모든 노드는 최대 2개의 자식 노드를 가질 수 있으며, 왼쪽 자식이 순서가 먼저이다. 노드 n��

www.acmicpc.net

 

이진 트리의 전위, 중위, 후위 순회에 대한 문제다. 

 

일단 전위 순회의 결과와 중위 순회의 결과로 후위 순회를 구할 수 있도록 문제가 주어진다고 했다. 

 

그러면 어떻게 전위 순회와 중위 순회로 후위 순회를 구할 수 있을까. 

 

전위는 방문이 먼저인 VLR구조이고, 중위는 LVR구조이다. 

 

방문을 먼저한다는게 후위 순회를 위해서 이진트리구조를 알 수 있는 핵심이라고 생각한다. 

 

무조건 root부터 순회를 시작하는 구조에서 방문을 먼저한다 -> 가장 먼저 출력되는 값 = root

 

그래서 문제해결방법은 subtree안의 subtree를 계속해서 구하는 방식으로 진행된다.

 

예시에서

 

a = 3 2 1 4

b = 2 3 4 1

 

이 각각 순회의 결과라고 한다면 3은 무조건 root이다. 

그러고 중위 순회의 구조를 조사해보면 LVR, 방문이 중간이다. 

 

여기서는 dfs의 작동원리를 이해하고 있으면 쉽게 이해할 수 있지만 그렇지 않으면 어려울 수도 있다.

 

방문이 중간이라는 소리는 모든 L-subtree를 조사하고 나서 방문 후 R-subtree를 조사한다는 소리이다. 

그러므로 중위 순회에서 3의 위치를 기준으로 왼쪽은 L-subtree, 오른쪽은 R-subtree이다. 

 

따라서 문제는 재귀적으로 진행된다. 

 

a에서 root를 구함

root = 3 

왼쪽에 노드 2가 존재.

오른쪽에 4, 1이 존재.

 

subtree로 진행 

a에서 root를 구함

root = 2

왼쪽에 존재 x

오른쪽에 존재 x

 

다시 진행 

a에서 root를 구함

root = 1

왼쪽에 4

오른쪽에 존재 x

 

이렇게 재귀적으로 진행된다 .

 

그래서 우리가 해야될 일은 조사 범위를 함수의 매개변수로 넣어서 subtree의 조사범위를 제한시켜준다. 

 

	solve(l, tmp-1, index+1); 왼쪽 서브트리
	solve(tmp+1, r, index+tmp-l+1); 오른쪽 서브트리

 index의 값을 설정해주는게 꽤 까다로웠는데 그냥 뭐를 구하려고 하는지만 잘 생각해보면 구할 수 있는 것 같다.

 

이제 언제 후위 연산을 위해서 값을 출력시켜야 할 지 생각해보자

 

후위 연산은 LRV이다. 따라서 l_subtree와 r_subtree 뒤에 원하는 값을 출력한다. 

 

#include<iostream>
using namespace std;
#define MAX 1001

int T, n;
int a[MAX];
int b[MAX];

void solve(int l, int r,  int index) {
	if (l > r) return;
	int tmp = b[a[index]];
	solve(l, tmp-1, index+1);
	solve(tmp+1, r, index+tmp-l+1);
	cout << a[index] << " ";
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> T;
	for (int i = 0; i < T; i++) {
		cin >> n;
		for (int j = 0; j < n; j++) {
			cin >> a[j];
		}
		for (int j = 0; j < n; j++) {
			int tmp;
			cin >> tmp;
			b[tmp] = j;
		}
		solve(0, n - 1, 0);
		cout << "\n";
	}

	
}