알고리즘/문제 풀이

11724번: 연결 요소의 개수

Themion 2022. 1. 7. 14:22

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

 

11724번: 연결 요소의 개수

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주

www.acmicpc.net

입력으로 주어진 그래프의 개수를 세는 문제이므로, 그래프를 그대로 저장한 뒤 그래프를 탐색해 그래프의 개수를 출력하거나, 그래프에 크루스칼 기법을 적용한 뒤 만들어진 트리의 루트 노드의 개수를 출력하면 된다.

- 그래프 탐색

#include <iostream>

using namespace std;

#define MAX_N 1000

// graph[i][j]: 노드 i와 노드 j를 잇는 에지가 존재한다면 true
bool graph[MAX_N][MAX_N];
// 노드의 개수
int N;

// 노드 node와 연결된 각 노드를 dfs
void dfs(int node) {
    // 현재 노드를 탐색함을 표시한 뒤
    graph[node][node] = false;

    // 현재 노드와 연결되어 있고 미탐색한 노드가 있다면
    for (int i = 0; i < N; i++) if (graph[i][i] && graph[node][i]) {
        // 연결을 해제한 뒤 노드 i를 탐색
        graph[node][i] = graph[i][node] = false;
        dfs(i);
    }
}

int main() {
    // 입출력 속도 향상
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // M: 에지의 개수, a, b: 에지가 잇는 두 노드, ans: 연결 요소의 개수
    int M, a, b, ans = 0;

    // 노드의 개수와 에지의 개수를 입력받은 뒤 각 에지에 대해
    for (cin >> N >> M; M--;) {
        // 에지를 입력받아 graph에 저장
        cin >> a >> b;
        graph[a][b] = graph[--b][--a] = true;
    }
    // i번 노드에서 i번 노드로 이동하는 에지는 없으므로
    // graph[i][i]를 visit처럼 사용
    for (int i = 0; i < N; i++) graph[i][i] = true;

    // 모든 노드를 방문하면서 그래프의 개수를 계산
    for (int i = 0; i < N; i++) if (graph[i][i]) {
        dfs(i);
        ans++;
    }

    // 그래프의 개수를 출력
    cout << ans << '\n';

    return 0;
}

 

- 크루스칼 기법

#include <iostream>

using namespace std;

#define MAX_N 1000

// parent[i]: 노드 i의 부모 노드
int parent[MAX_N + 1];

// 노드 node가 속한 트리의 루트 노드를 재귀적으로 탐색
int root(int node) {
    if (parent[node] && parent[node] != node)
        return parent[node] = root(parent[node]);
    return parent[node] = node;
}

int main() {
    // 입출력 속도 향상
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // visit[i]: 루트 노드가 i인 그래프를 탐색했다면 true
    bool visit[MAX_N + 1] = { 0, };
    // N: 노드의 수, M: 에지의 수, a, b: 각 에지를 이루는 두 노드, ans: 그래프의 수
    int N, M, a, b, ans = 0;

    // 노드와 에지의 수를 입력받은 뒤 각 에지에 대해
    for (cin >> N >> M; M--; ) {
        // 에지를 이루는 두 노드를 입력받고
        cin >> a >> b;

        // 두 노드가 속한 트리의 루트 노드를 계산한 뒤
        a = root(a);
        b = root(b);
        // 두 트리를 연결
        parent[a] = b;
    }

    // 각 노드가 속한 트리의 루트 노드만을 방문한 뒤
    for (int i = 1; i <= N; i++) visit[root(i)] = true;
    // 루트 노드의 개수를 계산해 ans에 저장
    for (int i = 1; i <= N; i++) ans += visit[i];

    // 루트 노드의 개수, 즉 연결 요소의 개수를 출력
    cout << ans << '\n';
    
    return 0;
}

'알고리즘 > 문제 풀이' 카테고리의 다른 글

11726번: 2×n 타일링  (0) 2022.01.07
11725번: 트리의 부모 찾기  (0) 2022.01.07
11723번: 집합  (0) 2022.01.06
11721번: 열 개씩 끊어 출력하기  (0) 2022.01.06
11720번: 숫자의 합  (0) 2022.01.06