백준 1043 거짓말 [자바]
in Develop / Solving
baekjoon 1043 거짓말
java
문제 분석
- 굳이 이런 인생을 살아야 하고 싶은 지민이가
- 파티에서 거짓말을 할건데,
- 진실이 아는 사람이 한명이라도 있으면 거짓말을 못함.
- 근데 한 사람이 여러 파티에 가서, 한번은 거짓을 듣고 한번은 진실을 들으면, 거짓말이 들키므로 이것도 일관되게 해야 함.
입력조건
int_사람 수N int_파티 수M
int_진실을 아는 사람 수 int[]_진실을 아는 사람들 번호
M줄에 걸쳐서{
int_파티에 오는 사람 수 int[]_파티에 오는 사람 명단
}
풀이과정
- 보자마자 서로소집합이라는 생각이 들었다.
- 진실을 아는 사람들을 한 그룹으로 묵고,
- 전 파티에 걸쳐서 사람들을 묶은 뒤에,
진실을 아는 그룹의 부모와 다른 부모인 애들만 오는 파티에 거짓말이 가능.
- 한번 입력받은 파티를 전부 순회하며 서로소 집합을 구한 뒤,
- 파티를 다시 순회하며 거짓말을 할 수 있는 집단 구하기.
코드 구성
- 유니온 파인드
static int findp(int x) {
if(p[x] == x) return p[x];
else return p[x] = findp(p[x]);
}
static void union(int x, int y) {
p[findp(y)] = findp(x);
}
- 진실을 알고 있는 사람이 0일 때의 처리.
StringTokenizer st = new StringTokenizer(br.readLine());
int num = Integer.parseInt(st.nextToken());
// 진실을 알고있는 사람 번호
int truth = 0;
try {
// 한명 받아보고, 불가능하면 넘기기.
truth = Integer.parseInt(st.nextToken());
} catch(Exception e) {
// 진실을 알고있는 사람의 수가 0일 때의 처리.
System.out.println(M);
return;
}
전체 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.stream.Stream;
public class BJ1043거짓말 {
static int[] p;
static int[][] party;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
// 사람 수
int N = Integer.parseInt(st.nextToken());
// 파티 수
int M = Integer.parseInt(st.nextToken());
// 서로소 집합 생성
p = new int[N+1];
for(int i = 0; i <= N; i++) p[i] = i;
// 진실을 아는 사람 입력받기.
st = new StringTokenizer(br.readLine());
int num = Integer.parseInt(st.nextToken());
// 진실을 알고있는 사람.
int truth = 0;
try {
truth = Integer.parseInt(st.nextToken());
} catch(Exception e) {
// 진실을 알고있는 사람의 수가 0일 때의 처리.
System.out.println(M);
return;
}
for(int i = 1; i < num; i++)
union(truth, Integer.parseInt(st.nextToken()));
// 파티 입력받기.
party = new int[M][];
for(int i = 0; i < M; i++)
party[i] = Stream.of(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
// 입력받기 끝.
for(int p = 0; p < M; p++) {
// 모든 파티에 대해,
int main = party[p][1];
// 합치기.
for(int i = 2; i <= party[p][0]; i++)
union(main, party[p][i]);
}
// 순회하면서 거짓말 할 수 있는 파티 세기.
int count = 0;
truth = findp(truth);
par : for(int p = 0; p < M; p++) {
for(int i = 1; i <= party[p][0]; i++) {
if(truth == findp(party[p][i]))
continue par;
}
// 여기에 도착하면, 거짓말 가능
count++;
}
System.out.println(count);
}
static int findp(int x) {
if(p[x] == x) return p[x];
else return p[x] = findp(p[x]);
}
static void union(int x, int y) {
p[findp(y)] = findp(x);
}
}
이런 너랑 친구해주는 애들한테 고마워해라 지민아