넘치게 채우기

[BOJ] 3865 - 학회원 본문

PS/BOJ

[BOJ] 3865 - 학회원

riveroverflow 2025. 4. 30. 09:37
반응형

https://www.acmicpc.net/problem/3865

BOJ - 학회원

문제 유형: 문자열 처리, bfs, 그래프, 파싱

문제 난이도: Gold IV

시간 제한: 1초

메모리 제한: 128MB

문제

상근이는 Sogang ACM-ICPC Team의 회장이다. 서강대학교 컴퓨터 학생들은 하나 또는 그 이상의 학회에 소속되어 있다. 상근이는 학생들이 어떤 학회에 소속되어 있는지 조사해보려고 한다.

상근이는 학회원의 정보를 다음과 같이 작성한다. 아래 예시는 sisobus와 weissblume은 icpc의 학회원이라는 뜻이다.

icpc:weissblume,sisobus.

콜론(:)의 앞에는 학회의 이름이 쓰여 있고, 뒤에는 학회원이 주어진다.

어떤 학회는 모든 회원이 다른 학회에 소속되어 있을 수도 잇다. 따라서, 학회원을 적는 곳에 학회의 이름을 적을 수도 있다.

slug:sisobus,minhyeok,icpc,exupery.

icpc에 소속되어 있는 사람은 slug에도 소속되어 있다는 뜻이다. 즉, slug의 학회원은 아래와 같다.

slug:sisobus,minhyeok,weissblume,sisobus,exupery.

이 경우에 sisobus는 두 번 등장한다. 중복되는 사람의 이름을 하나로 줄이게 되면, 아래와 같이 하나로 줄여서 작성할 수 있다.

slug:sisobus,minhyeok,weissblume,exupery.

학회의 회원 정보가 주어졌을 때, 각 학회의 학회원이 몇 명인지 구하는 프로그램을 작성하시오.

상근이가 작성하는 방법에는 학회의 이름이 중첩될 수도 있다. 아래 예시에서 one에 소속된 회원은 abckhw 한 명이다.

one:another.
another:yetanother.
yetanother:abckhw.

 

입력

입력은 여러 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 학회의 수 n이 주어진다. n은 100을 넘지 않는 양의 정수이다. 다음 n개 줄에는 각 학회의 학회원 정보가 문제에서 설명한 형식으로 주어진다. 콜론(:) 앞은 학회 이름이고, 그 뒤쪽은 회원의 이름이 콤마(,)로 구분되어져 있다. 각 정보의 마지막에는 마침표(.)가 하나 주어진다.

학회의 이름은 서로 다르다. 학회원 정보에서 주어지는 회원이 학회 이름이 아닌 경우에는 사람의 이름이다.

입력으로 주어지는 학회 정보에서 순환을 이루는 정보는 없다.

각 그룹 또는 사람의 이름은 비어있지 않은 문자열이며, 길이가 1과 15 사이이다. 또, 알파벳 소문자로만 이루어져 있다.

각 학회에 속한, 그룹이나 사람의 수는 1 이상 10 이하이다.

입력의 마지막 줄에는 0이 하나 주어진다.

 

출력

각 테스트 케이스에 대해서, 제일 처음으로 주어지는 학회에 포함되어 있는 회원의 수를 출력한다.

 

풀이

a:b,c,d.의 꼴에서, a를 source, b,c,d를 destination으로 생각하고 유향 그래프를 만들어주면 된다.

그러고 맨 첫 번째 문장의 source부터 bfs를 돌려서, 방문한 노드들 중, 진출차수가 0인 노드의 개수를 구하면 된다.

 

코드

C++

#include <bits/stdc++.h>

using namespace std;

int main(int argc, char *argv[]) {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n;
    while ((cin >> n) && n != 0) {
        unordered_map<string, vector<string>> adj;
        unordered_map<string, bool> visited;
        string start;
        for (int i = 0; i < n; i++) {
            string str;
            cin >> str;

            int l = 0, r = 0;
            while (str[r] != ':') {
                r++;
            }
            string src = str.substr(0, r - l);
            visited[src] = false;
            if (i == 0) start = src;
            r++;
            l = r;

            while (r < str.size() && str[r] != '.') {
                while (str.size() && str[r] != '.' && str[r] != ',') {
                    r++;
                }
                string dst = str.substr(l, r - l);
                adj[src].emplace_back(dst);
                visited[dst] = false;
                r++;
                l = r;
            }
        }

        queue<string> q;
        q.emplace(start);
        visited[start] = true;

        int ans = 0;
        while (!q.empty()) {
            string curr = q.front();
            q.pop();

            if (adj[curr].size() == 0) ans++;
            for (const auto &next : adj[curr]) {
                if (!visited[next]) {
                    visited[next] = true;
                    q.emplace(next);
                }
            }
        }

        cout << ans << "\n";
    }

    return 0;
}
반응형

'PS > BOJ' 카테고리의 다른 글

[BOJ] 16988 - Baaaaaaaaaduk2 (Easy)  (0) 2025.05.02
[BOJ] 2937 - 블록 정리  (0) 2025.05.01
[BOJ] 28435 - 배수 피하기  (0) 2025.04.29
[BOJ] 23880 - Walking Home  (0) 2025.04.28
[BOJ] 2262 - 토너먼트 만들기  (0) 2025.04.27