본문 바로가기
알고리즘 문제 풀이/백준

백준 1068 트리 c++, Kotlin, Java (dfs,bfs)

by 옹구스투스 2021. 7. 21.
반응형

문제

트리에서 리프 노드란, 자식의 개수가 0인 노드를 말한다.

트리가 주어졌을 때, 노드 하나를 지울 것이다. 그 때, 남은 트리에서 리프 노드의 개수를 구하는 프로그램을 작성하시오. 노드를 지우면 그 노드와 노드의 모든 자손이 트리에서 제거된다.

예를 들어, 다음과 같은 트리가 있다고 하자.

현재 리프 노드의 개수는 3개이다. (초록색 색칠된 노드) 이때, 1번을 지우면, 다음과 같이 변한다. 검정색으로 색칠된 노드가 트리에서 제거된 노드이다.

이제 리프 노드의 개수는 1개이다.

입력

첫째 줄에 트리의 노드의 개수 N이 주어진다. N은 50보다 작거나 같은 자연수이다. 둘째 줄에는 0번 노드부터 N-1번 노드까지, 각 노드의 부모가 주어진다. 만약 부모가 없다면 (루트) -1이 주어진다. 셋째 줄에는 지울 노드의 번호가 주어진다.

출력

첫째 줄에 입력으로 주어진 트리에서 입력으로 주어진 노드를 지웠을 때, 리프 노드의 개수를 출력한다.

알고리즘 분류

풀이

그래프 탐색 문제이다.

우선 주어진 간선을 연결해 주고, bfs 혹은 dfs로 삭제할 노드와, 삭제할 노드의 자식 노드들을 모두 삭제한다.

//삭제된 노드는 bool을 true로 바꿔서 삭제됨을 표시한다.

 

삭제해야 할 노드를 모두 삭제한 후, 0부터 n-1노드까지 리프 노드의 개수를 센다.

여기서 리프 노드의 조건은, 노드가 삭제되지 않았고, 자식 노드들이 없다면 리프 노드이다.

 

아래는 자식 노드가 삭제돼서, 리프 노드가 된 경우를 처리하지 못해서 통과하지 못했던 반례이다.

 

2
-1 0
1

답 : 1

 

코드1(cpp)

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

bool deleted[50];
vector<int> graph[50];
int answer = 0;
int n;
//n>0 n<=50

//노드 삭제
void bfs(int start) {
	queue<int> q;
	q.push(start);
		while (!q.empty()) {
			int cur = q.front();
			q.pop();
			deleted[cur] = true;
			for (int i = 0; i < graph[cur].size(); i++) {
				int next = graph[cur][i];
				if (deleted[next])
					continue;
				q.push(next);
			
			}
		}


}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	
	cin >> n;
	int start = 0;
	for (int i = 0; i < n; i++) {
		int num;
		cin >> num;
		if (num == -1) {
			start = i;
			continue;
		}
		graph[num].push_back(i);
	}
	int delete_num;
	cin >> delete_num;
	bfs(delete_num);

	//리프노드 탐색
	for (int i = 0; i < n; i++) {
		//
		if(!deleted[i]){
			int j=-1;
			for (j = 0; j < graph[i].size(); j++) {
				if (!deleted[graph[i][j]])
					break;
			}
			if (j == graph[i].size())
				answer++;
		}
	}
	cout << answer;
	return 0;
}

코드2(Kotlin)

import java.util.*

val br = System.`in`.bufferedReader()
lateinit var edge: Array<ArrayList<Int>>
var answer = 0
var delete = 0
fun dfs(cur: Int){
    if(cur==delete) return
    if(edge[cur].isEmpty()){
        answer++
        return
    }
    else{
        var isLeaf = true
        for(next in edge[cur]){
            if(next==delete) continue
            dfs(next)
            isLeaf = false
        }
        if(isLeaf){
            answer++
            return
        }
    }
}

fun main() = with(System.out.bufferedWriter()){

    //input
    val n = br.readLine().toInt()
    var root =0
    edge = Array(n){ArrayList()}
    val tk = StringTokenizer(br.readLine())
    for(i in 0 until n){
        val num = tk.nextToken().toInt()
        if(num<0){
            root = i
        }
        else{
            edge[num].add(i)
        }
    }
    delete = br.readLine().toInt()

    //solve
    dfs(root)

    //output
    write("$answer")
    close()
}

코드3(Java)

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;

public class Main {

	
	static ArrayList<Integer>[] edge;
	static int n;
	static int delete;
	static int root;
	
	static int dfs(int cur) {
		if(edge[cur].isEmpty()) {
			return 1;
		}
		int sum=0;
		int cnt=0;
		for(int i=0; i<edge[cur].size();i++) {
			int next = edge[cur].get(i);
			if(next==delete) continue;
			cnt++;
			sum+=dfs(next);
		}
		if(cnt==0) return 1;
		return sum;
	}
	
	public static void main(String[] args) throws Exception {

		//System.setIn(new FileInputStream("input.txt"));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		//input
		n = Integer.parseInt(br.readLine());
		edge = new ArrayList[n];
		for(int i=0; i<n; i++) {
			edge[i] = new ArrayList();
		}
		StringTokenizer tk = new StringTokenizer(br.readLine());
		for(int i=0; i<n;i++) {
			int num = Integer.parseInt(tk.nextToken());
			if(num<0) {
				root = i;
				continue;
			}
			edge[num].add(i);
		}
		delete = Integer.parseInt(br.readLine());
		if(delete==root) {
			System.out.println(0);
			br.close();
			return;
		}
		//solve,output
		System.out.println(dfs(root));
		br.close();
	
		return;
	}	
}
반응형

댓글