Skip to content

Latest commit

 

History

History
986 lines (595 loc) · 21.8 KB

_백준_강의_기초(9)_큐와_그래프.md

File metadata and controls

986 lines (595 loc) · 21.8 KB

10845번: 큐

정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여섯 가지이다. (push X, pop, size, empty, front, back)

## 10845번: 큐
#### 정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.
#### 명령은 총 여섯 가지이다. (push X, pop, size, empty, front, back)


import sys

n = int(sys.stdin.readline())

queue = [0] * n # 모든 명령어가 push라고 해도 최대 n칸 필요
begin = 0
end = 0

for _ in range(n):
    cmd, *val = sys.stdin.readline().split()

    if cmd == 'push':
        queue[end] = int(*val)
        end += 1

    elif cmd == 'pop':
        if begin == end: # 비어 있을 때
            print(-1)

        else:
            print(queue[begin])
            queue[begin] = False # 임의
            begin += 1

    elif cmd == 'size':
        print(end - begin)


    elif cmd == 'empty':
        if begin == end: # 비어 있을 때
            print(1)

        else:
            print(0)

    elif cmd == 'front':
        if begin == end: # 비어 있을 때
            print(-1)

        else:
            print(queue[begin])


    elif cmd == 'back':
        if begin == end: # 비어 있을 때
            print(-1)

        else:
            print(queue[end-1]) # end는 다음 인덱스로 넘어가 있는 상태이므로 -1 해줘야 함

10866번: 덱

정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 여덟 가지이다. (push_front X, push_back X, pop_front, pop_back, size, empty, front, back)

## 10866번: 덱
#### 정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.
#### 명령은 총 여덟 가지이다. (push_front X, push_back X, pop_front, pop_back, size, empty, front, back)


import sys
from collections import deque


n = int(sys.stdin.readline())

d = deque # 덱 선언


for _ in range(n):
    s = sys.stdin.readline().split()

    cmd = s[0]

    if cmd == 'push_front':
        d.appendleft(int(s[1]))


    elif cmd == 'push_back':
        d.append(int(s[1]))


    elif cmd == 'pop_front':
        if d:
            print(d.popleft())

    else: # 비어 있을 때
        print(-1)


    elif cmd == 'size':
        print(len(d)) # len 함수


    elif cmd == 'empty':
        print(0 if d else 1)

    elif cmd == 'front':
        if d: # 비어 있을 때
            print(d[0])

    else: # 비어 있을 때
        print(-1)


    elif cmd == 'back':
        if d: # 비어 있을 때
            print(d[-1])

    else: # 비어 있을 때
        print(-1)
# 런타임 에러

import sys
from collections import deque


n = int(input())

d = deque # 덱 선언


for _ in range(n):
  cmd, *val = input().split()

  if cmd == 'push_front':
    d.appendleft(int(*val))


  elif cmd == 'push_back':
    d.append(int(*val))


  elif cmd == 'pop_front':
    if d:
      print(d.popleft())

    else: # 비어 있을 때
      print(-1)


  elif cmd == 'size':
    print(len(d)) # len 함수


  elif cmd == 'empty':
    if d:
      print(0)

    else: # 비어 있을 때
      print(1)

  elif cmd == 'front':
    if d: # 비어 있을 때
      print(d[0])

    else: # 비어 있을 때
      print(-1)


  elif cmd == 'back':
    if d: # 비어 있을 때
      print(d[-1])

    else: # 비어 있을 때
      print(-1)
15
push_back 1



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-15-19774eeb705e> in <module>()
     21 
     22   elif cmd == 'push_back':
---> 23     d.append(int(*val))
     24 
     25 


TypeError: descriptor 'append' requires a 'collections.deque' object but received a 'int'
s = 'push_back 1'.split()
print(s)
['push_back', '1']
s[0]
'push_back'
s[1]
'1'
s1 = 'front'.split()
s1[0]
'front'

13023번 : ABCDE

첫째 줄에 사람의 수 N (5 ≤ N ≤ 2000)과 친구 관계의 수 M (1 ≤ M ≤ 2000)이 주어진다. 0는 1와 친구다. 1는 2와 친구다. ... N-2는 N-1와 친구다. 위와 같은 친구 관계가 존재하는지 안하는지 구하는 프로그램을 작성하시오.

## 13023번 : ABCDE
#### 첫째 줄에 사람의 수 N (5 ≤ N ≤ 2000)과 친구 관계의 수 M (1 ≤ M ≤ 2000)이 주어진다. 0는 1와 친구다. 1는 2와 친구다. ... N-2는 N-1와 친구다. 위와 같은 친구 관계가 존재하는지 안하는지 구하는 프로그램을 작성하시오.

import sys


n, m = map(int, input().split())

edges = []
a = [[False]*n for _ in range(n)] # 인접 행렬
g = [[] for _ in range(n)] # 인접 리스트

for _ in range(m):
    u, v = map(int, input().split())
    edges.append((u, v))
    edges.append((v, u)) # 양방향

    a[u][v] = a[v][u] = True # 양방향

    g[u].append(v)
    g[v].append(u) # 양방향


m *= 2 # 양방향
for i in range(m):
    for j in range(m):
        A, B = edges[i]
        C, D = edges[j]

        if A == B or A == C or A == D or B == C or B == D or C == D:
            continue

        if a[B][C] == False: # 또는 if not a[B][C]
            continue

        for E in g[D]:
            if E == A or E == B or E == C or E == D:
                continue

            print(1)
            sys.exit(0)

print(0) # 끝까지 1이 출력되지 않는 경우는 불가능한 경우
5 4
0 1
1 2
2 3
3 4
1



An exception has occurred, use %tb to see the full traceback.


SystemExit: 0



/usr/local/lib/python3.7/dist-packages/IPython/core/interactiveshell.py:2890: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
  warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
n, m = map(int, input().split())

edges = []
a = [[False]*n for _ in range(n)] # 인접 행렬
g = [[] for _ in range(n)] # 인접 리스트

for _ in range(m):
    u, v = map(int, input().split())
    edges.append((u, v))
    edges.append((v, u)) # 양방향

    a[u][v] = a[v][u] = True # 양방향

    g[u].append(v)
    g[v].append(u) # 양방향
5 4
0 1
1 2
2 3
3 4
edges
[(0, 1), (1, 0), (1, 2), (2, 1), (2, 3), (3, 2), (3, 4), (4, 3)]
a
[[False, True, False, False, False],
 [True, False, True, False, False],
 [False, True, False, True, False],
 [False, False, True, False, True],
 [False, False, False, True, False]]
g
[[1], [0, 2], [1, 3], [2, 4], [3]]

1260번: DFS와 BFS

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

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

from collections import deque

n, m, start = map(int, input().split())

a = [[] for _ in range(n+1)]
check = [False] * (n+1)

# 그래프 만들기
for _ in range(m):
    u, v = map(int, input().split())
    a[u].append(v)
    a[v].append(u) # 양방향

# 문제 조건 (단, 방문할 수 있는 정점이 여러 개인 경우에는 정점 번호가 작은 것을 먼저 방문)
for i in range(n):
      a[i].sort()


# DFS
def dfs(x):
    global check
    check[x] = True # 방문처리
    print(x, end = ' ')

    for y in a[x]: # x번째 정점과 연결된 간선(정점)들 중에
        if check[y] == False: # 아직 방문하지 않은 곳이 있다면,
            dfs(y) # 다음 재귀 진행

    # BFS
    def bfs(x):
        check = [False] * (n+1) # 다시 생성
        q = deque()

        check[start] = True
        q.append(start)

        while q: # 큐가 비어있다면 => 종료
            x = q.popleft()
            print(x, end = ' ') # 현재 큐에 담겨있는 요소 중 가장 앞 정점으로 탐색

            for y in a[x]: # x번째 정점과 연결된 간선(정점)들 중에
                if check[y] == False: # 아직 방문하지 않은 곳이 있다면,
                    check[y] = True # 방문처리
                    q.append(y) # 및 방문한 큐 리스트에 담기(?)



dfs(start)
print()
bfs(start)
print()
5 5 3
5 4
5 2
1 2
3 4
3 1
3 1 2 5 4 
3 1 4 2 5 
from collections import deque

qq = deque()
qq.append(1)
qq.append(2)
print(qq.popleft())
1
qq
deque([1, 2])

프로그래머스 - 깊이/너비 우선 탐색(DFS/BFS) > 네트워크

## 프로그래머스 - 깊이/너비 우선 탐색(DFS/BFS) > 네트워크

from collections import deque


def solution(n, computers):
    answer = 0
    
    check = [False] * (n)
    q = deque()
    q.append(0)
    
    
    while False in check: # 방문하지 않은 곳이 없을 때까지 반복
        node = check.index(False)
        q.append(node)

        while q:
            x = q.popleft()
            check[x] = True
            #print(x)

            for i in range(0, n):
                if x == i: # 자기자신은 모두 1로 표현된다고 문제에서 주어졌으므로
                    continue # pass

                if computers[x][i] == 1 and check[i] == False:
                    check[i] == True
                    q.append(i)

        answer += 1
    #print(q)
    return answer
# 정답

from collections import deque

def solution(n, computers):
    visit = [False for _ in range(n)]
    que = deque([0])
    ans = 0

    while visit.count(False) != 0:
        node = visit.index(False)
        que.append(node)

        while que:
            visitedNode = que.popleft()
            visit[visitedNode] = True

            for i in range(n):
                if computers[visitedNode][i] != 0 and visit[i] == False:
                    que.append(i)
                    visit[i] = True
        ans += 1
    return (ans)
solution(3, [[1, 1, 0], [1, 1, 0], [0, 0, 1]])
2
solution(3, [[1, 1, 0], [1, 1, 1], [0, 1, 1]])
1
que = deque([0])
print(que)
deque([0])

1707번: 이분 그래프

그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.

그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.

## 1707번: 이분 그래프
#### 그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.
#### 그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.


import sys
sys.setrecursionlimit(1000000)

#input = sys.stdin.readline() # 입력함수 변경

t = int(sys.stdin.readline())

for _ in range(t): # Testcase 만큼 반복
    n, m = map(int, sys.stdin.readline().split()) # 정점 수, 간선 수

    a = [[] for _ in range(n)] # 인접 리스트
    color = [0] * n # 0: 없음 1: A에 속함 2: B에 속함

  # 그래프 생성
    for _ in range(m):
        u, v = map(int, sys.stdin.readline().split())
        a[u-1].append(v-1)
        a[v-1].append(u-1) # 양방향 (조건(각 정점에는 1부터 V까지 차례로 번호가 붙어 있다.) 때문에 -1)


    def dfs(x,c):
        color[x] = c

        for y in a[x]:
            if color[y] == 0: # 1)) 아직 방문 안해서 '없음'으로 지정되어 있는 상태라면,
                if not dfs(y, 3-c): # 조기종료 (인접 노드(next)는 (3-c)의 색을 가져야 함 => dfs 결과가 중간에 False가 한번이라도 나올 시)
                    return False

                elif color[y] == color[x]: # 2)) 또는 이미 방문은 했다면, => 방문은 안해도 색은 비교! => 현재 노드가 인접노드와 같은 색깔에 속한다면
                    return False # 조기종료 (이분그래프의 조건: 서로 인접한 정점이 같은 색이면 이분 그래프가 아니다.)

        # 반복문을 모두 돌 동안 이상이 없었다면    
        return True # 이분그래프가 맞음



    ans = True

    for i in range(n):
        if color[i] == 0:
            if not dfs(i, 1):
                ans = False

    print('YES' if ans else 'NO')
2
3 2
1 3
2 3
YES
4 4
1 2
2 3
3 4
4 2
YES

2667번: 단지번호 붙이기

여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다.

지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수를 오름차순으로 정렬하여 출력하는 프로그램을 작성하시오.

## 2667번: 단지번호 붙이기
#### 여기서 연결되었다는 것은 어떤 집이 좌우, 혹은 아래위로 다른 집이 있는 경우를 말한다. 대각선상에 집이 있는 경우는 연결된 것이 아니다.
#### 지도를 입력하여 단지수를 출력하고, 각 단지에 속하는 집의 수를 오름차순으로 정렬하여 출력하는 프로그램을 작성하시오.

# 단지: "연결요소"의 수
# 단지의 크기: 연결요소에 포함된 "정점"의 갯수

# <인접리스트>의 목적: 한 정점과 연결된 다른 정점(또는 간선)을 효율적으로 찾기 위함
# 하지만, 이 문제에서는 <인접리스트>를 따로 정의해주지 않아도 된다 => 주어진 2차원 배열을 이용하면 됨.

from collections import deque, Counter
from functools import reduce

# 이동가능한 4 방향 (왼쪽, 오른쪽, 위, 아래)
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]

# 단지 번호/네트워크 번호 구하는 BFS 구현
def bfs(x, y, cnt):
    q = deque()
    q.append((x, y))
    group[x][y] = cnt # cnt: 단지번호 (네트워크 번호)

    while q:
        x, y = q.popleft()

        for k in range(4):
            nx, ny = x+dx[k], y+dy[k]

            if 0 <= nx < n and 0 <= ny < n: # 범위에 대한 조건 (필수)
                if a[nx][ny] == 1 and group[nx][ny] == 0 : # <조건> 해당 좌표에 집이 있고(a 배열) & 아직 방문한 적이 없으면(group 배열)
                    q.append((nx, ny)) # 방문할 큐에 추가 &&
                    group[nx][ny] = cnt # 인접한 4분위 좌표에 해당 "단지 번호/네트워크 번호" 업데이트


# 문제 입출력
n = int(input())
a = [list(map(int, list(input()))) for _ in range(n)]

group = [[0]*n for _ in range(n)] # 방문여부 파악 & 단지번호 업데이트 할 배열 하나 만들어줌
cnt = 0

for i in range(n):
    for j in range(n):
        if a[i][j] == 1 and group[i][j] == 0: # <조건> 해당 좌표에 집이 있고(a 배열) & 아직 방문한 적이 없으면(group 배열)
            cnt += 1 # 다음 단지번호로 넘어가서
            bfs(i, j, cnt) # 구현해둔 BFS 함수 실행



ans = reduce(lambda x, y : x+y, group)
ans = [x for x in ans if x > 0]
ans = sorted(list(Counter(ans).values()))

print(cnt)
print('\n'.join(map(str, ans)))
7
0110100
0110101
1110101
0000111
0100000
0111110
0111000
3
7
8
9
n= 5

[0]*n
[[0]*n for _ in range(n)]
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]

2178번: 미로 탐색

NxM 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. (최단 거리 구하기 문제 -> BFS !!)

## 2178번: 미로 탐색
#### NxM 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. (최단 거리 구하기 문제 -> BFS !!)

# 최단 거리 문제
from collections import deque

# 이동가능한 4 방향 (왼쪽, 오른쪽, 위, 아래)
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]

n, m = map(int, input().split())
a = [list(map(int, list(input()))) for _ in range(n)]


dist = [[-1]*m for _ in range(n)] # -1: 아직 방문 안함, 0이상의 거리: 해당 좌표까지 가는데 걸리는 최단거리
q = deque()

q.append((0, 0)) # 문제에서 (1, 1)이 출발점으로 주어짐
dist[0][0] = 1 # 출발점 방문처리 겸 이동 거리 "1" 초기화 (문제 조건: 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.)

while q:
    x, y = q.popleft()

    for k in range(4):
        nx, ny = x+dx[k], y+dy[k]

        if 0<=nx<n and 0<=ny<m:
            if dist[nx][ny] == -1 and a[nx][ny] == 1: # 아직 방문하지 않았었고, 주어진 배열에서 길이 존재하는 좌표일 때
                q.append((nx, ny)) # (1)방문할 큐에 추가
                dist[nx][ny] = dist[x][y] + 1 # (2)dist(거리) 배열에 방문처리 겸 && 지금까지 합산된 거리 업데이트


print(dist[n-1][m-1])
4 6
101111
101010
101011
111011
15

7576번: 토마토

보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다.

토마토가 모두 익을 때까지의 최소 날짜를 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

## 7576번: 토마토
#### 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다.
#### 토마토가 모두 익을 때까지의 최소 날짜를 출력해야 한다. 만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고, 토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.


# 최소 일수 문제

from collections import deque

# 이동가능한 4 방향 (왼쪽, 오른쪽, 위, 아래)
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]

m, n = map(int, input().split())
a = [list(map(int, input().split())) for _ in range(n)]


q = deque()
dist = [[-1]*m for _ in range(n)] # -1: 아직 방문 안함, 0이상의 거리: 해당 좌표까지 가는데 걸리는 최단거리


# 가장 먼저 등장하는 '익은 토마토(1)' 찾기 (출발점)
for i in range(n):
    for j in range(m):
        if a[i][j] == 1:
            dist[i][j] = 0 # [거리 행렬] 모든 가능한 출발점 방문처리 겸 이동 거리 "0" 초기화
            q.append((i,j)) # [방문할 큐] 해당 좌표 추가



while q:
    x, y = q.popleft()

    for k in range(4):
        nx, ny = x+dx[k], y+dy[k]

        if 0<=nx<n and 0<=ny<m:
            if dist[nx][ny] == -1 and a[nx][ny] == 0: # 아직 방문하지 않았었고, 주어진 배열에서 '안 익은 토마토' 좌표일 때
                q.append((nx, ny)) # (1)방문할 큐에 추가
                dist[nx][ny] = dist[x][y] + 1 # (2)dist(거리) 배열에 방문처리 겸 && 지금까지 합산된 거리 업데이트
                ###a[nx][ny] = 1 # 익은 토마토로 변경
        

ans = max([max(row) for row in dist])
# (예외 처리)
for i in range(n):
    for j in range(m):
        if a[i][j] == 0 and dist[i][j] == -1:
            ans = -1



print(ans)
3 3
-1 -1 1
-1 1 -1
1 -1 -1
0
[[-1, -1, 0], [-1, 0, -1], [0, -1, -1]]
max(dist)
[0, -1, -1]
max(max(dist))
0

7562번: 나이트의 이동

체스판 위의 나이트는 현재 있는 칸에서 이동하려고 하는 칸까지 최소 몇번만에 이동할 수 있을지 출력

## 7562번: 나이트의 이동
#### 체스판 위의 나이트는 현재 있는 칸에서 이동하려고 하는 칸까지 최소 몇번만에 이동할 수 있을지 출력


# 최소 이동 횟수

from collections import deque

dx = [1, 2, 2, 1, -1, -2, -2, -1]
dy = [2, 1, -1, -2, -2, -1, 1, 2]


t = int(input())

for _ in range(t):
    n = int(input())
    sx, sy = map(int, input().split())
    ex, ey = map(int, input().split())

    d = [[-1]*n for _ in range(n)] # 거리 배열 (방문 여부 & 지금까지 최단 거리)
    q = deque()

    d[sx][sy] = 0
    q.append((sx, sy))

    # BFS
    while q:
        x, y = q.popleft()
    
        for k in range(8):
            nx, ny = x+dx[k], y+dy[k]
            if 0 <= nx < n and 0 <= ny < n: # 좌표 이동 중 거리 범위 조건 주기
                if d[nx][ny] == -1: # 아직 방문하지 않았다면, (체스판의 모든 곳은 이동가능하므로, 간선이 존재하는지 여부는 체크 패스)
                    d[nx][ny] = d[x][y] + 1 # (1)최단 거리 업데이트
                    q.append((nx, ny)) # (2)방문할 큐에 추가


    print(d[ex][ey])
3
8
0 0
7 0
5
100
0 0
30 50
28
10
1 1
1 1
0