문제
https://www.acmicpc.net/problem/1043
문제 요약
지민이는 각 파티에서 거짓말을 하고 싶어한다.
하지만, 몇몇 사람들은 이미 이야기의 진실을 알고 있다.
따라서, 이런 사람들이 파티에 왔을 경우, 지민이는 진실을 이야기할 수 밖에 없다.
당연히 어떤 사람이 다른 파티에서 진실을 듣고, 또다른 파티에서는 거짓말을 들었을 경우가 없도록 피해야 한다.
거짓말을 할 수 있는 파티 수의 최대를 출력한다.
코드
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// uf[i]: i번 사람의 그룹 번호
int uf[55];
// t_uf[i]: i번 그룹이 진실을 아는지 여부
bool t_uf[55];
// 파티 정보 저장
vector<int> party[55];
// 진실을 알고 있는 사람 리스트
vector<int> t_person;
// x번 사람의 그룹 번호 탐색 (그룹 대표 번호)
int find(int x) {
if (uf[x] == x) {
return x;
}
uf[x] = find(uf[x]);
return uf[x];
}
// x번 사람과 y번 사람의 그룹 병합
void union_(int x, int y) {
x = find(x);
y = find(y);
uf[x] = y;
}
int main() {
// 입출력 시간 단축
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// 사람 수, 파티 수
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
uf[i] = i;
}
// 진실을 알고 있는 사람 수
int t;
cin >> t;
for (int i = 0; i < t; i++) {
int num;
cin >> num;
t_person.push_back(num);
}
// 파티 정보 입력
for (int i = 0; i < m; i++) {
int cnt;
cin >> cnt;
vector<int> tmp(cnt);
for (int j = 0; j < cnt; j++) {
cin >> tmp[j];
}
// 같은 파티에 참여한 사람들의 그룹 병합
for (int j = 1; j < cnt; j++) {
union_(tmp[0], tmp[j]);
}
party[i] = tmp;
}
// 진실을 아는 사람이 속한 그룹을 체크
for (int p : t_person) {
int root = find(p);
t_uf[root] = true;
}
// 파티별로 거짓말이 가능한지 체크
int answer = 0;
for (int i = 0; i < m; i++) {
// 기본적으로 거짓말 가능하다고 가정
bool canLie = true;
// 파티 참석 인원 중, 진실을 알고 있는 사람이 속한 그룹의 사람이라면 거짓말 불가
for (int person : party[i]) {
if (t_uf[find(person)]) {
canLie = false;
break;
}
}
if (canLie) answer++;
}
cout << answer;
return 0;
}
코드 설명
그룹을 관리해야 하므로, Union-Find 분리 집합을 이용하여 문제를 해결한다.
1. 진실을 알고 있는 사람 정보를 벡터에 저장한다.
2. 각 파티에 참여하는 사람의 정보를 입력 받고, 같은 파티에 참여한 사람들의 그룹을 병합한다.
3. 각 그룹 내 진실을 알고 있는 사람이 존재하는지 체크한다. (그룹 체크)
4. 각 파티 내 진실을 알고 있는 그룹에 속한 사람이 존재하는지 체크한다. (파티 체크)
'Algorithm Problems > 그래프' 카테고리의 다른 글
[백준/C++] 16234번: 인구 이동 (1) | 2025.02.12 |
---|---|
[백준/C++] 1707번: 이분 그래프 (0) | 2025.02.04 |
[백준/C++] 11779번: 최소비용 구하기 2 (1) | 2025.01.24 |
[백준/C++] 13325번: 이진 트리 (0) | 2025.01.19 |
[백준/C++] 2636번: 치즈 (1) | 2024.12.28 |