알고리즘

[파이썬] 단계별 백준 문제 풀기 - 1260번 DFS/BFS (DFS와 BFS)

햄❤️ 2021. 3. 16. 20:21
반응형

문제링크

 

1260번: DFS와 BFS

첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사

www.acmicpc.net

문제

그래프를 DFS로 탐색한 결과와 BFS로 탐색한 결과를 출력하는 프로그램을 작성하시오. 단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문하고, 더 이상 방문할 수 있는 점이 없는 경우 종료한다. 정점 번호는 1번부터 N번까지이다.

입력

첫째 줄에 정점의 개수 N(1 ≤ N ≤ 1,000), 간선의 개수 M(1 ≤ M ≤ 10,000), 탐색을 시작할 정점의 번호 V가 주어진다. 다음 M개의 줄에는 간선이 연결하는 두 정점의 번호가 주어진다. 어떤 두 정점 사이에 여러 개의 간선이 있을 수 있다. 입력으로 주어지는 간선은 양방향이다.

출력

첫째 줄에 DFS를 수행한 결과를, 그 다음 줄에는 BFS를 수행한 결과를 출력한다. V부터 방문된 점을 순서대로 출력하면 된다.


<<소스코드>>

import sys
from collections import deque

#n = 정점의 갯수, p = 간선의 갯수, s = 시작 정점 번호
n,p,s = map(int,sys.stdin.readline().split())
graph = {} #인접 정점들을 담을 빈 그래프

# 정점 갯수 n개만큼 빈 그래프 생성
for i in range(1,n+1):
    graph[i] = []

#그래프 채우기, 간선갯수만큼
for i in range(p):
    a,b = map(int,sys.stdin.readline().split())
    graph[a].append(b)
    graph[b].append(a)

#BFS 함수 생성, 큐 이용
# 시작노드를 큐에 추가 -> 큐에서 뽑아서 현재노드 지정 -> visited에 없으면 visited에 추가
# 인접노드 탐색(오름차순 정렬) -> 인접노드가 visited에 없으면 큐에 추가 -> 처음으로 돌아가 반복 
def bfs(ad_graph,start):
    queue = deque()
    queue.append(start)
    visited = []
    if start not in ad_graph:
        visited.append(start)
        return
    while queue:
        current_node = queue.popleft()
        if current_node not in visited:
            visited.append(current_node)
            ad_graph[current_node].sort()
        for ad_node in ad_graph[current_node]:
            if ad_node not in visited:
                queue.append(ad_node)
    return visited

#DFS 함수 생성, 스택 이용
#시작점 스택에 추가 -> 스택에서 뽑아서 현재 노드 지정 -> visited에 없으면 visite 추가
# 인접노드 탐색(역순 정렬!!) -> 인접노드가 visited에 없으면 스택에 추가 -> 반복
def dfs(ad_graph,start):
        stack = []
        stack.append(start)
        visited_dfs = []
        if start not in ad_graph:
            visited_dfs.append(start)
            return
        while stack:
            current_node = stack.pop()
            if current_node not in visited_dfs:
                visited_dfs.append(current_node)
                ad_graph[current_node].sort(reverse=True)
            for ad_node in ad_graph[current_node]:
                if ad_node not in visited_dfs:
                    stack.append(ad_node)
        return visited_dfs

#join함수를 이용하여 공백을 기준으로 리스트 벗고 문자열로 바꿔서 print
print(' '.join(map(str,dfs(graph,s))))
print(' '.join(map(str,bfs(graph,s))))

<<결과값>>

5 5 3
5 4
5 2
1 2
3 4
3 1

3 1 2 5 4
3 1 4 2 5

계속 난이도 하 문제만 풀다가 간만에 문제 풀었는데 이렇게 오래걸리기 있긔없긔...(좌절)

 

[틀렸던것, 몰랐던 것]

 

 1) 단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문

   -> 문제에서 번호가 작은 것부터 탐색하라고 했다. 흑... 자세히 읽자

       queue(BFS)에서는 오름차순 정렬 sort()를 해줘야하고, stack(DFS)에서는 역순(내림차순) 정렬을 해줘야 정점번호가 작은 것부터 방문하게 된다는 점!

 

2) 만약, start에 간선이 연결되지 않았다면? 시작점에 간선이 없는 경우를 대비해 아래 코드를 추가했다. 

   start에 간선이 없는 경우를 생각지도 못했다. 다른 팀원분이 얘기해주지 않았다면 평생 몰랐을듯! 

if start not in ad_graph:
        visited.append(start)
        return

3) 리스트를 출력하면 안된다. 숫자만 출력해줘야 함! 

예제의 답이 1 2 4 3 인데 나는 [1,2,4,3] 이렇게 출력하고 있었다. 왜 틀렸지? 이러고 있었네...주륵

.join은 리스트에 특정 구분자를 추가하여 문자열로 변환하는 것이다! ' ' 사이에 쉼표(,)를 넣으면 쉼표로 구문되어 리스트값이 [] 대괄호를 벗고 튀어나온다. 단, 예제의 답은 숫자이므로 str으로 변환해줘야하는 점! 

print(' '.join(map(str,dfs(graph,s))))

 

728x90
반응형