거의 알고리즘 일기장

백준 13306번 _ 트리 본문

알고리즘 문제풀이

백준 13306번 _ 트리

건우권 2020. 6. 26. 16:38

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

 

13306번: 트리

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에는 트리의 정점의 개수와 질의의 개수를 나타내는 두 정수 N과 Q (1 ≤ N, Q ≤ 200,000)가 주어진다. 다음 N-1개의 줄의 i번째 줄에는 정점 i+1의 부��

www.acmicpc.net

풀이방법

문제가 구하라는 바는 다음과 같다.

1. 간선을 끊어라.

2. 경로가 있는지 확인해라.

 

이 문제는 간선을 모두 끊으므로, 먼저 간선을 모두 끊어놓고 주어진 물음들을 반대로 실행하면 쉽게 정답을 구할수있다.


코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>

using namespace std;

stack<vector<int>> order;
stack<string> ans;
int originParents[200001];
int N, Q;

int parents[200001];

void parentsInit()
{
	for (int i = 1; i <= N; i++)
	{
		parents[i] = i;
		originParents[i] = i;
	}
}

int getParent(int a)
{
	if (parents[a] == a) return a;
	else return parents[a] = getParent(parents[a]);
}

void UNION(int a, int b)
{
	a = getParent(a);
	b = getParent(b);

	parents[b] = a;
}

void Input()
{
	cin >> N >> Q;
	parentsInit();
	for (int i = 2; i < (N - 1) + 2; i++)
		cin >> originParents[i];

	int x, b, c, d;
	for (int i = 0; i < (N - 1) + Q; i++)
	{
		vector<int> question;
		cin >> x;
		question.push_back(x);

		if (x == 0)
		{
			cin >> b;
			question.push_back(b);
		}
		else
		{
			cin >> c >> d;
			question.push_back(c);
			question.push_back(d);
		}
		order.push(question);
	}
}

void Solve()
{
	while (!order.empty())
	{
		vector<int>question = order.top();
		order.pop();
		int b, c, d;
		if (question[0] == 0)
		{
			b = question[1];
			parents[b] = originParents[b];
		}
		else
		{
			c = question[1];
			d = question[2];

			if (getParent(c) == getParent(d))
				ans.push("YES");
			else
				ans.push("NO");
		}
	}

	while(!ans.empty())
	{
		cout << ans.top() << '\n';
		ans.pop();
	}
}

int main()
{
	Input();
	Solve();
	
	return 0;
}

풀이방법을 보고 정말 획기적이라고 생각했다.

반응형

'알고리즘 문제풀이' 카테고리의 다른 글

프로그래머스lv3 _ 디스크 컨트롤러  (0) 2020.09.04
백준 4195번 _ 친구 네트워크  (0) 2020.06.26
백준 1655번 _ 가운데를 말해요  (0) 2020.06.24
N과 M  (0) 2020.06.24
백준 9251, 9252, 1958 _ LCS 1, 2, 3  (0) 2020.06.17
Comments