728x90
https://www.acmicpc.net/problem/20040
힌트
더보기
유니온 파인드를 사용하면 그래프의 사이클 존재 여부를 빠르게 판별할 수 있다.
풀이
더보기
각 정점을 이어나갈 때 사이클이 어느 순서에 생기는지 알아야 하는 문제이다.
각 정점을 이을 때마다 DFS를 이용한 사이클 검출을 실시하면 $O(m^{2})$의 시간 복잡도로 인해 시간 초과를 받을 것이다.
하지만 유니온 파인드를 이용하면 아주 짧은 시간으로 사이클 여부를 판단할 수 있다.
각 정점을 union 하면서 만약 부모가 같은 정점을 마주치면 트리 상태에서 간선을 한 개 추가하는 것이므로 곧 사이클이 존재하는 그래프가 됨을 알 수 있다.
m개의 쿼리를 진행하면서 사이클이 생기는지 검사하도록 하자.
전체 코드
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
int n, m;
struct ufind
{
vector<int> parent, rank;
ufind(int n): parent(n), rank(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 vnion(int u, int v)
{
u = find(u), v = find(v);
if (u == v) return false;
if (rank[v] < rank[u])
swap(u, v);
parent[u] = v;
if (rank[u] == rank[v])
++rank[v];
return true;
}
};
int main()
{
cin.tie(nullptr);
ios::sync_with_stdio(false);
cin >> n >> m;
ufind st(n);
for (int i = 0; i < m; ++i)
{
int a, b;
cin >> a >> b;
if (st.vnion(a, b))
continue;
else
{
cout << i + 1;
return 0;
}
}
cout << 0;
}
제출 기록
728x90
'백준 > 유니온 파인드' 카테고리의 다른 글
[USACO] 백준 1774 - 우주신과의 교감 (0) | 2021.08.17 |
---|---|
백준 1976 - 여행가자 (0) | 2019.09.17 |