백준 1043 - 거짓말
Updated:
Java
1043 번 - 거짓말
문제
N개의 사람 수와 M개의 파티 수가 주어진다.
지민이는 모든 파티에 참석하며, 각 파티마다 최대한 거짓말을 많이 하고 싶어한다.
하지만, 진실을 아는 사람이 존재하며 진실을 아는 사람과 같은 파티에 속한 사람들은 모두 진실을 알게 된다.
이때, 지민이가 거짓말쟁이로 알려지지 않으면서, 과장된 이야기를 할 수 있는 파티 개수의 최댓값을 구하는 프로그램을 작성하시오.
접근 방법
DisJoint Set으로 각 파티에 속한 사람들 끼리 묶는다.
묶은 뒤, 각 파티에 속한 사람들은 서로 Parent Node가 같게 된다.
다시 한번 파티의 사람들을 확인하며, 그 파티의 구성원들이 전부 진실의 아는 자와 다른 그룹이어서 Parent Node가 다른지 확인한다.
전부 다르면 결과를 증가 시킨다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, m, result;
static int[] parents;
static List<int[]> party;
static List<Integer> truth; // 진실을 아는 자
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
parents = new int[n + 1];
truth = new ArrayList<>();
party = new ArrayList<>();
stk = new StringTokenizer(br.readLine());
int k = stoi(stk.nextToken());
int man;
// 진실을 아는 자를 세팅
for(int i = 0; i < k; i++) {
man = stoi(stk.nextToken());
truth.add(man);
}
int[] partyMan;
// 파티 세팅
for(int i = 0; i < m; i++) {
stk = new StringTokenizer(br.readLine());
man = stoi(stk.nextToken());
partyMan = new int[man];
for(int j = 0; j < man; j++) {
partyMan[j] = stoi(stk.nextToken());
}
party.add(partyMan);
}
// disjoint set으로 같은 파티에 온 사람끼리 묶는다
init();
int a;
for(int i = 0; i < m; i++) {
partyMan = party.get(i);
a = partyMan[0];
for(int j = 1; j < partyMan.length; j++) {
union(a, partyMan[j]);
}
}
// 각 파티에 참석한 사람이 진실의 아는자와 같은 파티에 있는지 확인
boolean isKnown;
for(int i = 0; i < m; i++) {
partyMan = party.get(i);
isKnown = false;
// 각 파티를 탐색하여 파티 인원 중 진실을 아는 사람이 있는지 확인
for(int j = 0; j < partyMan.length; j++) {
if(chkInTruth(partyMan[j])) {
isKnown = true;
break;
}
}
if(!isKnown) { // 아무도 진실을 모르면 정답 증가
result++;
}
}
System.out.println(result);
br.close();
}
// 현재 사람의 root parent와 진실의 아는 사람의 root parent가 같은지 확인
static boolean chkInTruth(int man) {
for(int i : truth) {
if(findSet(man) == findSet(i)) {
return true;
}
}
return false;
}
// --------- disjoint set -------
static void init() {
for(int i = 1; i <= n; i++) {
parents[i] = i;
}
}
static int findSet(int num) {
if(parents[num] == num) {
return num;
}
return parents[num] = findSet(parents[num]);
}
static boolean union(int a, int b) {
int aRoot = findSet(a);
int bRoot = findSet(b);
if(aRoot == bRoot)
return false;
int min = Math.min(aRoot, bRoot);
parents[aRoot] = min;
parents[bRoot] = min;
return true;
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
Disjoint Set을 응용한 문제
개선할 점
없습니다.