알고리즘/문제풀이

[백준 20040번] 사이클 게임

Ohnim · 오님 2024. 9. 22. 00:02

문제 링크

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

 

문제 요약

\(N\)개의 점이 있다. 이때 서로 다른 두 개의 점을 연결하는 선분들이 차례대로 주어졌을 때, 사이클이 생기는 순간을 찾는 문제이다.

 

문제 풀이

각 점을 노드로, 선분을 간선으로 하는 무향 그래프로 모델링을 한다. 새로운 간선을 추가할 때마다 두 노드가 같은 집합에 속해 있는지 확인한다. 만약 같은 집합에 속해 있다면, 해당 간선을 추가하면 사이클이 형성되는 것이다. 반대로, 같은 집합에 속해있지 않으면 두 집합을 합쳐서 하나의 집합으로 만든다. 유니온 파인드(Union Find) 자료구조를 이용해 집합을 효율적으로 관리할 수 있으며, 제한시간 내에 문제를 해결할 수 있다.

 

소스 코드

더보기
더보기
#include <stdio.h>
#include <vector>
#include <algorithm>

using namespace std;

// Union Find 자료구조
struct UnionFind {
    vector<int> parent;
    vector<int> rank;
    
    UnionFind(int n): rank(n, 1), parent(n) {
        for (int i = 0 ; i < n ; ++i) {
            parent[i] = i;
        }
    }
    
    int find(int u) {
        if (u == parent[u]) {
            return u;
        }
        
        return parent[u] = find(parent[u]);
    }
    
    bool merge(int u, int v) {
        u = find(u);
        v = find(v);
        
        if (u == v) {
            return false;
        }
        
        if (rank[u] > rank[v]) {
            swap(u, v);
        }
        
        parent[u] = v;
        
        if (rank[u] == rank[v]) {
            ++rank[v];
        }
        
        return true;
    }
};

int main() {
    int n, m;
    
    scanf("%d%d", &n, &m);
    
    UnionFind uf(n + 1);
    
    for (int i = 1 ; i <= m ; ++i) {
        int u, v;
        
        scanf("%d%d", &u, &v);
        
        if (!uf.merge(u, v)) {
            printf("%d\n", i);
            
            return 0;
        }
    }
    
    puts("0");
}