티스토리 뷰
문제 링크
문제
우리 나라는 가족 혹은 친척들 사이의 관계를 촌수라는 단위로 표현하는 독특한 문화를 가지고 있다. 이러한 촌수는 다음과 같은 방식으로 계산된다. 기본적으로 부모와 자식 사이를 1촌으로 정의하고 이로부터 사람들 간의 촌수를 계산한다. 예를 들면 나와 아버지, 아버지와 할아버지는 각각 1촌으로 나와 할아버지는 2촌이 되고, 아버지 형제들과 할아버지는 1촌, 나와 아버지 형제들과는 3촌이 된다.
여러 사람들에 대한 부모 자식들 간의 관계가 주어졌을 때, 주어진 두 사람의 촌수를 계산하는 프로그램을 작성하시오.
입력
사람들은 1, 2, 3, …, n (1≤n≤100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다.
각 사람의 부모는 최대 한 명만 주어진다.
출력
입력에서 요구한 두 사람의 촌수를 나타내는 정수를 출력한다. 어떤 경우에는 두 사람의 친척 관계가 전혀 없어 촌수를 계산할 수 없을 때가 있다. 이때에는 -1을 출력해야 한다.
문제 풀이
DFS, BFS 문제는 2차원 배열을 사용하는 문제와 이번 문제같이 간선을 사용하는 문제로 크게 나뉘는 것 같습니다.
직접 그래프를 만들어줘야하기 때문인지 몰라도 저는 개인적으로 이렇게 간선으로 주어지는 문제가 좀 더 어려운거 같아요 ㅠ
이 문제는 촌수 계산을 하는 문제인데, 결국 그래프 탐색 문제였습니다.
예제를 그래프로 그려보면..
위와 같이 생긴 그래프가 만들어지고 문제는 3,7을 잇는 최단거리를 구하는 문제입니다.
따라서 DFS로 풀려면 모든 경로를 구해서 가장 짧은 거리를 구하면 되고
BFS로 풀려면 탐색하다가 최초로 나올 때의 값이 답입니다.
물론 이 문제는 예제에서도 보이듯이 연결되어 있지 않을 수 도 있기 때문에 이 경우엔 -1을 출력해주시면 됩니다.
공부를 위해서 DFS, BFS 방법 모두로 풀어보았는데 데이터의 수가 그렇게 많지는 않기 때문에 속도는 똑같이 나오는거 같습니다.
저는 이런 문제가 나오면 늘 자료구조가 복잡해지는거 같은데.. 좀 더 나은 풀이법이 있는지 공부해봐야겠습니다.
감사합니다.
소스 코드
import Foundation
func dfsSolution() {
let n = Int(readLine()!)!
let secondLine = readLine()!.split(separator: " ").map({Int(String($0))!})
let m = Int(readLine()!)!
let inf = 77777777
var graph: [Int: [[Int]]] = [:]
for i in 1...n {
graph[i] = []
}
for _ in 0..<m{
let info = readLine()!.split(separator: " ").map({Int(String($0))!})
graph[info[0]]!.append([info[0], info[1]])
graph[info[1]]!.append([info[1], info[0]])
}
var isVisited: [Int] = [Int](repeating: inf, count: n+1)
isVisited[secondLine[0]] = 0
var stack = graph[secondLine[0]]!
while !stack.isEmpty {
let now = stack.popLast()!
if isVisited[now[1]] > isVisited[now[0]] + 1 {
stack += graph[now[1]]!
isVisited[now[1]] = isVisited[now[0]] + 1
}
}
if isVisited[secondLine[1]] == inf {
print(-1)
} else {
print(isVisited[secondLine[1]])
}
}
class Queue<T>{
var enqueue: [T]
var dequeue: [T] = []
var isEmpty: Bool{
return enqueue.isEmpty && dequeue.isEmpty
}
var count: Int{
return enqueue.count + dequeue.count
}
init(_ queue:[T]){
self.enqueue = queue
}
func push(_ n: T){
enqueue.append(n)
}
func pop() -> T?{
if dequeue.isEmpty{
dequeue = enqueue.reversed()
enqueue.removeAll()
}
return dequeue.popLast()
}
}
func bfsSolution() {
let n = Int(readLine()!)!
let secondLine = readLine()!.split(separator: " ").map({Int(String($0))!})
let m = Int(readLine()!)!
let inf = 77777777
var graph: [Int: [[Int]]] = [:]
for i in 1...n {
graph[i] = []
}
for _ in 0..<m{
let info = readLine()!.split(separator: " ").map({Int(String($0))!})
graph[info[0]]!.append([info[0], info[1]])
graph[info[1]]!.append([info[1], info[0]])
}
var isVisited: [Int] = [Int](repeating: inf, count: n+1)
isVisited[secondLine[0]] = 0
let queue = Queue([[[Int]]]())
queue.push(graph[secondLine[0]]!)
while !queue.isEmpty {
let now = queue.pop()!
for i in 0..<now.count {
if now[i][1] == secondLine[1] {
if isVisited[now[i][1]] < isVisited[now[i][0]] + 1 {
print(isVisited[now[i][1]])
return
} else {
print(isVisited[now[i][0]] + 1)
return
}
}
if isVisited[now[i][1]] > isVisited[now[i][0]] + 1 {
isVisited[now[i][1]] = isVisited[now[i][0]] + 1
queue.push(graph[now[i][1]]!)
}
}
}
print(-1)
}
//dfsSolution()
bfsSolution()
'Algorithm > BaekJoon' 카테고리의 다른 글
[백준] 13023번 - ABCDE [Swift] (0) | 2021.04.04 |
---|---|
[백준] 5014번: 스타트링크 [Swift] (0) | 2021.03.15 |
[백준] 7562번 나이트의 이동 [Swift] (0) | 2021.01.07 |
[백준] 9205번 맥주 마시면서 걸어가기 [Swift] (0) | 2020.12.27 |
[백준] 10026번 적록색약 [Swift] (0) | 2020.12.05 |
- Total
- Today
- Yesterday
- operating
- Apple
- 프로그래밍
- 백준
- 자료구조
- document
- pattern
- Xcode
- 코딩테스트
- 코테
- 아이폰
- 문법
- design
- mac
- OSTEP
- Publisher
- DP
- 테이블뷰
- 동시성
- BFS
- IOS
- 앱개발
- 알고리즘
- operator
- Swift
- dfs
- OS
- System
- 스위프트
- Combine
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |