알고리즘/유니온 파인드
유니온 파인드 - 거짓말쟁이가 되긴 싫어
sim0609
2023. 4. 2. 02:14
<문제>
백준 - 1043: 여행 계획 짜기
https://www.acmicpc.net/problem/1043
1043번: 거짓말
지민이는 파티에 가서 이야기 하는 것을 좋아한다. 파티에 갈 때마다, 지민이는 지민이가 가장 좋아하는 이야기를 한다. 지민이는 그 이야기를 말할 때, 있는 그대로 진실로 말하거나 엄청나게
www.acmicpc.net
<문제 접근>
진실을 알고있는 사람들을 먼저 union 진행한 후, 각 파티에 나오는 사람들도 첫 번째 사람을 기준으로 union한다. 그리고나서 거짓말을 할 수 있는 사람들만 모인 파티를 세준다. 여기서 첫 번째 사람을 기준으로 union을 해야지 문제에 쉽게 접근할 수 있다.
<슈도 코드>
→ cnt 세는 코드는 전체 코드와 다름
<전체 코드>
#include <iostream>
#include <vector>
using namespace std;
static vector <int> v;
void Union(int f, int s);
int find(int n);
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
vector <int> t_g;
vector <vector<int>> n;
int human, party, t, t_p, num, num_human, cnt = 0;
cin >> human >> party;
cin >> t;
v.resize(human + 1, 0);
t_g.resize(t + 1, 0);
for (int i = 1; i <= human; i++) {
v[i] = i;
}
if (t == 0) {
cout << party;
return 0;
}
else {
for (int i = 1; i <= t; i++) {
cin >> t_p;
t_g[i] = t_p;
}
int k = t_g[1];
for (int i = 1; i <= t; i++) {
Union(k, t_g[i]);
}
n.resize(party + 1);
for (int i = 1; i <= party; i++) { // --> O(n^2)
cin >> num;
for (int j = 0; j < num; j++) {
cin >> num_human;
n[i].push_back(num_human);
}
for (int j = 0; j < num; j++) {
Union(n[i][0], n[i][j]); // --> 시간 복잡도 상수
}
for (int i = 1; i <= party; i++) { // --> O(n^2)
for (int j = 0; j < n[i].size(); i++) {
if (find(k) != find(n[i][j])) {
cnt += 1;
}
if (i == party) {
break;
}
}
}
cout << cnt;
return 0;
}
}
void Union(int f, int s) {
if (f > s) {
int tmp = f;
f = s;
s = tmp;
}
int f_find = find(f);
int s_find = find(s);
v[s_find] = f_find;
}
int find(int n) {
if (n == v[n]) {
return n;
}
else {
return v[n] = find(v[n]);
}
}