Codeforces Round #738 (Div. 2)-D1. Mocha and Diana (Easy Version)
falconlee236
·2021. 12. 19. 15:37
문제 설명
그래프이론에서 숲이란 사이클이 없는 무뱡향 그래프 이다. 이때 모든 노드와 연결될 필요 없다.
노원구에 사는 동환과 영준은 서로 친구이다. 이들은 모두 재벌이라서 각자 $1$부터 $n$까지 번호가 붙여있는 노드가 있는 숲을 가지고있다. 그리고 이들은 숲에 간선을 다음과 같은 방식으로 추가하는 것을 즐긴다.
- 간선을 추가하고 두 숲 모두 여전히 숲을 유지해야한다.
- 두 숲 모두 같은 간선을 추가해야 한다. 즉 간선 $(u, v)$를 동환이의 숲에 추가한다면 동일한 간선 $(u, v)$를 영준이에 숲에 추가해야하고 이 반대의 경우도 성립한다.
동환이와 영준이는 연결 할 수 있는 최대한 많은 간선을 연결하고 싶어한다.
Input
첫번째 줄에는 각각 노드의 수, 동환이의 숲에 있는 초기 간선의 수, 영준이의 숲에 있는 초기 간선의 수를 나타내는 정수 $n, m_1, m_2 (1 \le n \le 1000, 0 \le m_1, m_2 < n)$이 주어진다.
다음 $m_1$개의 줄에는 동환이의 숲에 있는 간선의 정보를 나타내는 두 정수 $n$과 $v (1 \le u, v \le n, u \neq v)$ 가 주어진다.
다음 $m_2$개의 줄에는 동환이의 숲에 있는 간선의 정보를 나타내는 두 정수 $n$과 $v (1 \le u, v \le n, u \neq v)$ 가 주어진다.
Output
첫번째 줄에는 동환이와 영준이가 최대로 추가할 수 있는 간선의 수 $h$를 출력한다.
다음 $h$개의 줄에는 둘이 추가한 간선의 정보를 나타내는 두 정수 $u$와 $v (1 \le u, v \le n, u \neq v)$ 를 출력한다.
Example
input
8 1 2
1 7
2 6
1 5
output
5
5 2
2 3
3 4
4 7
6 8
문제 접근
사용한 알고리즘: 그래프, DSU, 구성적 알고리즘, 완전탐색
걸린 시간 : 00:08
그냥 Disjoint-set union 자료구조을 이용하면 풀리는 문제이다. 대회에서 이거 풀기까지 4050분 정도 남았는데, 그냥 A번 풀지말고 이 문제 풀걸 그랬다. 그랬으면 14001500대 퍼포먼스가 찍혔을 것 같은데 아쉽다.
분리집합 자료구조는 이해하기 쉬우면서 그래프를 비롯한 다양한 알고리즘 문제에 사용되기 때문에 반드시 알아두고 STL에 없기 때문에 구현할 줄 알아한다.
사이클을 판별하는 방법은 두 노드의 부모가 같으면 사이클이라고 판별하면 된다. 그리고 노드의 부모를 찾는 함수는 find에 정의해 놓았다. $n$의 제한이 1000밖에 안되기 때문에 그냥 완전 탐색을 돌려서 모든 간선을 다 따져보는것이 속 편하다.
정답 코드
#include <iostream>
#include <vector>
using namespace std;
typedef struct _forest{
vector<int> root;
_forest(int n) : root(n + 1){
for(int i = 1; i <= n; i++) root[i] = i;
}
int find(int n){
if(root[n] == n) return n;
return root[n] = find(root[n]);
}
bool merge(int u, int v){
u = find(u);
v = find(v);
if(u == v) return false;
root[u] = v;
return true;
}
}forest;
int main() {
ios_base::sync_with_stdio(false); cout.tie(0); cin.tie(0);
int n, a, b; cin >> n >> a >> b;
forest f1(n), f2(n);
while(a--){
int x, y; cin >> x >> y;
f1.merge(x, y);
}
while(b--){
int x, y; cin >> x >> y;
f2.merge(x, y);
}
vector<pair<int, int>> ans;
for(int i = 1; i < n; i++){
for(int j = i + 1; j <= n; j++){
if(f1.find(i) != f1.find(j)){
if(f2.merge(i, j)){
f1.merge(i, j);
ans.push_back({i, j});
}
}
}
}
cout << ans.size() << "\n";
for(auto x : ans) cout << x.first << " " << x.second << "\n";
return 0;
}
'알고리즘 > codeforces' 카테고리의 다른 글
Codeforces Round #735 (Div. 2)-B. Cobb (0) | 2021.12.19 |
---|---|
Codeforces Round #735 (Div. 2)-A. Cherry (0) | 2021.12.19 |
Codeforces Round #738 (Div. 2)-C. Mocha and Hiking (0) | 2021.12.19 |
Codeforces Round #738 (Div. 2)-B. Mocha and Red and Blue (0) | 2021.12.19 |
Codeforces Round #738 (Div. 2)-A. Mocha and Math (0) | 2021.12.19 |