문제 풀이/탐색ㆍ그래프

[백준] 1260 (DFS와 BFS)

interfacer_han 2024. 9. 24. 13:09

#1 알고리즘

DFS 및 BFS 알고리즘을 알고 있는지 묻는 간단한 문제다. 하지만, 약간 신경 쓸 점이 3가지 있다.
 
1. 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문
인접 배열을 정렬하면 된다. 나는 퀵 정렬을 이용했다.

2. 정점의 개수 N(1 ≤ N ≤ 1,000)
문제에서 출제되는 정점은 1부터 시작한다. 즉, 1-based indexing을 사용하고 있다. 나는 이 문제를 풀기 위해 예전에 정리해 게시글로 남겨두었던 BFSDFS 알고리즘 코드를 그대로 가져다 쓸 건데, 문제는 해당 코드들은 정점이 0부터 시작한다는 조건 하에 짜여진 코드들이다. 즉, 정점이 0-based indexing을 사용하고 있다. 이 차이를 해소하기 위해서 '인접 배열들의 리스트(listOfAdjacencyArray)'의 첫 원소로 사용하지 않을 더미 배열을 넣어주었다 (#3의 코드 참조). 이러면 '인접 배열들의 리스트(listOfAdjacencyArray)'의 인덱스 번호와 정점 번호가 정확히 일치하게 된다. 즉, "어떤 정점 n의 인접 배열은 listOfAdjacencyArray[n]이다"라고 말할 수 있게 된다.

3. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다
인접 배열을 만들기 위해서 원소들을 채워나갈 때, 이미 존재하는 원소가 있는 지 검사하는 코드를 넣으면 된다.

#2 코드 - 코틀린

import java.util.*

val listOfAdjacencyArray: MutableList<ArrayList<Int>> = mutableListOf()

fun main() {
    val information = readln().split(" ")
    val vertexCount = information[0].toInt()
    val edgeCount = information[1].toInt()
    val startVertex = information[2].toInt()

    // (1) listOfAdjacencyArray[0] 추가. 그러나 사용하지 않을 것임
    listOfAdjacencyArray.add(arrayListOf())

    // 실제로 사용할 listOfAdjacencyArray[1] 부터 추가
    for (i: Int in 0..<vertexCount) {
        listOfAdjacencyArray.add(arrayListOf())
    }

    // (2) 인접 배열에 원소 넣기
    for (i: Int in 0..<edgeCount) {
        val vertexes = readln().split(" ")
        val vertexA = vertexes[0].toInt()
        val vertexB = vertexes[1].toInt()

        if (vertexB !in listOfAdjacencyArray[vertexA]) {
            listOfAdjacencyArray[vertexA].add(vertexB)
        }

        if (vertexA !in listOfAdjacencyArray[vertexB]) {
            listOfAdjacencyArray[vertexB].add(vertexA)
        }
    }

    // (3) 인접 배열 오름차순으로 정렬
    for (adjacencyArray in listOfAdjacencyArray) {
        quickSort(adjacencyArray, 0, adjacencyArray.size - 1)
    }

    // (4) DFS 수행
    val discovered = mutableSetOf<Int>()
    dfs(listOfAdjacencyArray, startVertex, discovered)

    println()

    // (5) BFS 수행
    bfs(listOfAdjacencyArray, startVertex)
}

fun quickSort(array: ArrayList<Int>, startIndex: Int, endIndex: Int) {

    // (startIndex < endIndex)의 의미: 배열의 크기가 2이상이다.
    if (startIndex < endIndex) {
        val pivotIndex = partitionAroundPivot(array, startIndex, endIndex)
        quickSort(array, startIndex, (pivotIndex - 1))
        quickSort(array, pivotIndex, endIndex)
    }
}

// endIndex가 pivot(기준)의 역할 수행
fun partitionAroundPivot(array: ArrayList<Int>, startIndex: Int, endIndex: Int): Int {
    var endOfLower = startIndex - 1

    for (i: Int in startIndex..<endIndex) {
        if (array[i] <= array[endIndex]) {
            // array[endIndex]보다 lower인 값 저장할 공간 확보를 위해 endOfLower++
            endOfLower++

            // array[i]와 array[endOfLower]의 값 서로 교환
            val temp = array[endOfLower]
            array[endOfLower] = array[i]
            array[i] = temp
        }
    }

    // array[endOfLower] 바로 뒤에 array[endIndex] (= 기준) 값이 오게 하기 위해서 endOfLower++
    endOfLower++

    // array[endIndex]과 array[endOfLower]의 값 서로 교환
    val temp = array[endOfLower]
    array[endOfLower] = array[endIndex]
    array[endIndex] = temp

    return endOfLower
}

fun dfs(listOfAdjacencyArray: List<ArrayList<Int>>, vertex: Int, discovered: MutableSet<Int>) {
    discovered.add(vertex)
    print("$vertex ")

    for (neighborVertex in listOfAdjacencyArray[vertex]) {
        if (neighborVertex !in discovered) {
            dfs(listOfAdjacencyArray, neighborVertex, discovered)
        }
    }
}

fun bfs(listOfAdjacencyArray: List<ArrayList<Int>>, startVertex: Int) {
    val queue: Queue<Int> = LinkedList()
    val discovered = mutableSetOf<Int>()

    queue.add(startVertex)
    discovered.add(startVertex)

    while (queue.isNotEmpty()) {
        val vertex = queue.remove()
        print("$vertex ")

        for (neighborVertex in listOfAdjacencyArray[vertex]) {
            if (neighborVertex !in discovered) {
                queue.add(neighborVertex)
                discovered.add(neighborVertex)
            }
        }
    }
}

'문제 풀이 > 탐색ㆍ그래프' 카테고리의 다른 글

[백준] 10026 (적록색약)  (1) 2024.11.27
[백준] 14940 (쉬운 최단거리)  (1) 2024.11.13
[백준] 2805 (나무 자르기)  (0) 2024.03.06
[백준] 1920 (수 찾기)  (0) 2023.12.25
[백준] 1654 (랜선 자르기)  (0) 2023.11.04