216. 탑승구

아현·2021년 7월 17일
0

Algorithm

목록 보기
224/400
  • 공항에는 G개의 탑승구가 있으며, 각각의 탑승구는 1번부터 G번까지의 번호로 구분됩니다.

  • 공항에는 P개의 비행기가 차례대로 도착할 예정이며, i번째 비행기를 1번부터 gᵢ번째 (1 ≤ gᵢ ≤ G) 탑승구 중 하나에 영구적으로 도킹해야 합니다.

    • 이때 다른 비행기가 도킹하지 않은 탑승구에만 도킹할 수 있습니다.
  • 또한 P개의 비행기를 순서대로 도킹하다가 만약에 어떠한 탑승구에도 도킹할 수 없는 비행기가 나오는 경우, 그 시점에서 공항의 운행을 중지합니다.

  • 공항의 관리자는 최대한 많은 비행기를 공항에 도킹하고자 합니다.

    • 비행기를 최대 몇 대 도킹할 수 있는지를 출력하는 프로그램을 작성하세요.

  • 입력조건

    • 첫째 줄에는 탑승구의 수 G(1 ≤ G ≤ 100,000)가 주어집니다.

    • 둘째 줄에는 비행기의 수 P(1 ≤ P ≤ 100,000)가 주어집니다.

    • 다음 P개의 줄에는 각 비행기가 도킹할 수 있는 탑승구의 정보 gᵢ가 주어집니다.

      • 이는 i번째 비행기가 1번부터 gᵢ 번째 탑승구 중 하나에 도킹할 수 있다는 의미 입니다.

  • 출력조건

    • 첫째 줄에 도킹할 수 있는 비행기의 최대 개수를 출력합니다.



1. 서로소 알고리즘



import sys
input = sys.stdin.readline
def find(x):
  if parent[x] == x:
    return x
  parent[x] = find(parent[x])
  return parent[x]

def union(a, b):
  a = find(a)
  b = find(b)
  if a != b:
    if a < b:
      parent[b] = a
    else: parent[a] = b

g = int(input())
p = int(input())
parent = [0] * (g + 1)

for i in range(1, g + 1):
  parent[i] = i

result = 0
for _ in range(p):
  data = find(int(input())) #현재 탑승구의 루트 확인
  if data == 0: #루트가 0이라면 종료
    break
  #그렇지 않다면 바로 왼쪽 집합과 합치기
  union(data, data - 1)
  result += 1
  
print(result)


  • 가능한 큰 번호의 탑승구로 도킹 수행한다고 가정

    • 도킹: union
  • 새로 도킹이 되면, 해당 집합을 바로 왼쪽에 있는 집합과 합친다.

    • But, 집합의 루트가 0이면 더 이상 도킹이 불가능한 것으로 판단



2. C++


#include <bits/stdc++.h>

using namespace std;

// 탑승구의 개수와 비행기의 개수
int g, p;
int parent[100001]; // 부모 테이블 초기화

// 특정 원소가 속한 집합을 찾기
int findParent(int x) {
    // 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
    if (x == parent[x]) return x;
    return parent[x] = findParent(parent[x]);
}

// 두 원소가 속한 집합을 합치기
void unionParent(int a, int b) {
    a = findParent(a);
    b = findParent(b);
    if (a < b) parent[b] = a;
    else parent[a] = b;
}

int main(void) {
    cin >> g >> p;

    // 부모 테이블상에서, 부모를 자기 자신으로 초기화
    for (int i = 1; i <= g; i++) {
        parent[i] = i;
    }

    int result = 0;
    for (int i = 0; i < p; i++) {
        int x;
        cin >> x;
        int root = findParent(x); // 현재 비행기의 탑승구의 루트 확인
        if (root == 0) break; // 현재 루트가 0이라면, 종료
        unionParent(root, root - 1); // 그렇지 않다면 바로 왼쪽의 집합과 합치기
        result += 1;
    }

    cout << result << '\n';
}
profile
Studying Computer Science

0개의 댓글