https://www.acmicpc.net/problem/1068
인접 리스트에 노드들 입력
기존 트리의 Leaf 노드 개수를 구함
DFS 로 노드를 삭제해가면서, Leaf 노드가 삭제되면
기존 Leaf 노드 개수에서 빼줌
예외 처리
1) 삭제 노드가 루트 노드인 경우 => 전체 삭제 후, 남은 Leaf 노드 개수는 0
2) 목표 노드 삭제 후, 삭제된 노드의 부모 노드가 Leaf 노드가 되는지 확인
e.g. 일직선으로 뻗친 트리에서 중간 노드 삭제할 경우
- 삭제 전, 기존 Leaf 노드 1개 -> 삭제 후, 남은 Leaf 노드 1개
List<Integer>[]
, ArrayList<Integer>[]
: 인접 리스트i
번 노드의 자식 노드들을 lists[i]
에 저장lists[0] = { 1, 2 }
, lits[1] = { 3, 4 }
트리의 특정 노드에서 시작하여 자식 노드로 탐색을 확장하는 경우 (전형적인 트리 탐색),
노드 방문 확인 배열boolean[] check
을 사용하지 않고도 해결가능
- 애초에 노드의 중복 방문이 발생하지 않음
- 트리를 거슬러 올라가는 상황(자식 노드 → 부모 노드) 발생 X
import java.io.*;
import java.util.*;
public class Main_DFS {
static int n; // 노드의 개수, 노드 번호: [0] ~ [n-1]
static List<Integer>[] lists; // 인접 리스트
static int deleteNode; // 지울 노드 번호
static int leafCount; // 출력 값: 노드 삭제 후, 남은 Leaf 노드 개수
static int rootNode; // 루트 노드 번호
/* deleteNode: 삭제할 노드 */
static void dfs(int delteNode) {
List<Integer> list = lists[delteNode]; // 삭제할 노드의 자식 노드들
if (list.isEmpty()) // 삭제할 노드가 Leaf 노드인 경우
leafCount--;
for (int child : list)
dfs(child);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
n = Integer.parseInt(br.readLine());
lists = new ArrayList[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++)
lists[i] = new ArrayList<>();
for (int i = 0; i < n; i++) {
int parent = Integer.parseInt(st.nextToken());
if (parent == -1) {
rootNode = i;
continue;
}
lists[parent].add(i); // parent 노드의 자식 노드들 저장
}
deleteNode = Integer.parseInt(br.readLine());
// 예외 처리 1) deleteNode 가 루트 노드인 경우 => 삭제 후, 남은 Leaf 노드 개수는 0
if (deleteNode == rootNode) {
System.out.println(0);
return;
}
// 기존 트리의 Leaf 노드 개수 계산
for (int i = 0; i < n; i++) {
if (lists[i].isEmpty())
leafCount++;
}
int parentNode = -1; // deleteNode 의 부모 노드
for (int i = 0; i < n; i++) {
for (int node : lists[i]) {
if (node == deleteNode) {
parentNode = i;
break;
}
}
}
lists[parentNode].remove(Integer.valueOf(deleteNode)); // deleteNode 삭제
dfs(deleteNode);
// 예외 처리 2) deleteNode 의 부모 노드가 Leaf 노드가 되는지 확인
if (lists[parentNode].isEmpty())
leafCount++;
System.out.println(leafCount);
}
}
인접 리스트에 노드들 입력
기존 트리의 Leaf 노드 개수를 구함
BFS 로 노드를 삭제해가면서, Leaf 노드가 삭제되면
기존 Leaf 노드 개수에서 빼줌
예외 처리
1) 삭제 노드가 루트 노드인 경우 => 전체 삭제 후, 남은 Leaf 노드 개수는 0
2) 목표 노드 삭제 후, 삭제된 노드의 부모 노드가 Leaf 노드가 되는지 확인
e.g. 일직선으로 뻗친 트리에서 중간 노드 삭제할 경우
- 삭제 전, 기존 Leaf 노드 1개 -> 삭제 후, 남은 Leaf 노드 1개
List<Integer>[]
, ArrayList<Integer>[]
: 인접 리스트i
번 노드의 자식 노드들을 lists[i]
에 저장lists[0] = { 1, 2 }
, lits[1] = { 3, 4 }
Queue<Integer>
, LinkedList<Integer>
: BFS트리의 특정 노드에서 시작하여 자식 노드로 탐색을 확장하는 경우 (전형적인 트리 탐색),
노드 방문 확인 배열boolean[] check
을 사용하지 않고도 해결가능
- 애초에 노드의 중복 방문이 발생하지 않음
- 트리를 거슬러 올라가는 상황(자식 노드 → 부모 노드) 발생 X
import java.io.*;
import java.util.*;
public class Main_BFS {
static int n; // 노드의 개수, 노드 번호: [0] ~ [n-1]
static List<Integer>[] lists; // 인접 리스트
static int deleteNode; // 지울 노드 번호
static int leafCount; // 출력 값: 노드 삭제 후, 남은 Leaf 노드 개수
static int rootNode; // 루트 노드 번호
static Queue<Integer> queue = new LinkedList<>();
static void bfs() {
while (!queue.isEmpty()) {
int deleteNode = queue.remove(); // 삭제할 노드
List<Integer> list = lists[deleteNode]; // 삭제할 노드의 자식 노드들
if (list.isEmpty()) // 삭제할 노드가 Leaf 노드인 경우
leafCount--;
for (int child : list)
queue.add(child);
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
n = Integer.parseInt(br.readLine());
lists = new ArrayList[n];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++)
lists[i] = new ArrayList<>();
for (int i = 0; i < n; i++) {
int parent = Integer.parseInt(st.nextToken());
if (parent == -1) {
rootNode = i;
continue;
}
lists[parent].add(i); // parent 노드의 자식 노드들 저장
}
deleteNode = Integer.parseInt(br.readLine());
// 예외 처리 1) deleteNode 가 루트 노드인 경우 => 삭제 후, 남은 Leaf 노드 개수는 0
if (deleteNode == rootNode) {
System.out.println(0);
return;
}
// 기존 트리의 Leaf 노드 개수 계산
for (int i = 0; i < n; i++) {
if (lists[i].isEmpty())
leafCount++;
}
int parentNode = -1; // deleteNode 의 부모 노드
for (int i = 0; i < n; i++) {
for (int node : lists[i]) {
if (node == deleteNode) {
parentNode = i;
break;
}
}
}
lists[parentNode].remove(Integer.valueOf(deleteNode)); // deleteNode 삭제
queue.add(deleteNode);
bfs();
// 예외 처리 2) deleteNode 의 부모 노드가 Leaf 노드가 되는지 확인
if (lists[parentNode].isEmpty())
leafCount++;
System.out.println(leafCount);
}
}