https://www.acmicpc.net/problem/1043
1043번: 거짓말
지민이는 파티에 가서 이야기 하는 것을 좋아한다. 파티에 갈 때마다, 지민이는 지민이가 가장 좋아하는 이야기를 한다. 지민이는 그 이야기를 말할 때, 있는 그대로 진실로 말하거나 엄청나게
www.acmicpc.net
코드설명
유니온파인드를 사용한 분리집합 문제입니다.
문제로직입니다.
- 저는 문제에서 진실을 아는 집단은 parent[] = 0 이라고 선언하였습니다. 즉, 진실을 알고있다면 parent[x] = 0 입니다.
- 각 입력마다 모든 분리집합을 연결시켜주기 위하여 각 파티에 참석하는 사람이 2명이상이라면 무조건 첫사람은 따로 입력받아서 unionParent(firstPeopleIdx, 나머지사람들 모두) 를 통하여 각 파티에 참석하는 사람들이 같은 곳을 바라보게 하였습니다. ( 이떄, parent[]가 모두 같아지지는 않을 수 있지만 이후에 findParent를 통하여 다 찾을 것이기에 같은 그룹으로만 보이도록 연결시켜주면 됩니다. )
- 각 파티그룹을 돌면서 이제 실제로 거짓말을 할 수 있는지 체크합니다. 이떄, findParent를 통해서 이미 연결된 각 집합들이 0의 집합에 속한지, 아니면 다른 집합인지를 통하여 거짓말을 할 수 있는지 알 수 있습니다.
좋은 TC가 있습니다. ( https://www.acmicpc.net/board/view/72203 )
4 5
1 1
1 1
1 2
1 3
2 4 2
2 4 1
answer
1
과정
0 0 2 3 4
0 0 2 3 4
0 0 2 3 4
0 0 2 3 2
0 0 0 3 2 -> findParent를 통해서 0 0 2 3 0 이 아닌 0 0 0 3 2 입니다. findParent는 부모의 배열을 변화시킵니다.
또한 해당 로직을 사용하기 위해서 findParent를 통해서 같은 그룹인지 확인해야합니다. (제 코드에서는 Parent를 비교하는것이 아닙니다.)
코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.regex.Pattern;
public class Main {
public static int N, M;
public static char[][] map;
public static int answer = 0;
public static int[] parent;
public static int[] knowTruth;
public static ArrayList<Integer>[] partyPeopleArr;
public static int findParent(int x) {
if( x == parent[x]) return x;
return parent[x] = findParent(parent[x]);
}
public static void unionParent(int a, int b) {
a = findParent(a);
b = findParent(b);
if( a < b ) parent[b] = a;
else parent[a] = b;
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
parent = new int[N+1];
for(int i=0; i<=N;i++) { //자기자신으로 초기화
parent[i] = i;
}
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
for(int i=0;i<a;i++) {
unionParent(0, Integer.parseInt(st.nextToken()));
}
partyPeopleArr = new ArrayList[M];
for(int i=0;i<M;i++) {
partyPeopleArr[i] = new ArrayList<Integer>();
}
for(int i=0;i<M;i++) {
st = new StringTokenizer(br.readLine());
int peopleCnt = Integer.parseInt(st.nextToken());
int firstPeopleIdx = Integer.parseInt(st.nextToken()); //처음의 값은 따로 받습니다.
partyPeopleArr[i].add(firstPeopleIdx);
for(int j=1; j<peopleCnt; j++) { //
int peopleIdx = Integer.parseInt(st.nextToken());
partyPeopleArr[i].add(peopleIdx);
unionParent(firstPeopleIdx, peopleIdx); //두개의 값 중 하나라도 진실을 안다면 그것에 맞추어 바뀌어질 것 입니다.
}
}
for(int i=0;i<M;i++) { //이제 모든 파티를 돌면서 각 파티에 참석할 수 있는지 알아냅니다.
boolean lieFlag = true;
for(int j=0;j<partyPeopleArr[i].size();j++) {
if(findParent(partyPeopleArr[i].get(j)) == 0) { //만약 한명이라도 진실을 안다면
lieFlag = false;
break;
}
}
if(lieFlag == true) {
System.out.println("WHY");
answer += 1;
}
}
System.out.println(answer);
}
}
'알고리즘 > Disjoint Set' 카테고리의 다른 글
[백준] 4195 친구 네트워크 - 유니온파인드(Union Find) + 해쉬맵(HashMap) JAVA (0) | 2023.09.05 |
---|---|
[백준] 16562 친구비 - 유니온파인드(Union Find) + 최소조건(Minimum) JAVA (0) | 2023.09.05 |
[백준] 1717 집합의 표현 - 유니온파인드(Union Find) JAVA (0) | 2023.09.05 |
[백준] 3197 백조의 호수 - BFS(너비우선탐색) + 유니온파인드(Union Find) JAVA (0) | 2023.08.25 |
[백준] 1976 여행 가자 - 유니온 파인드(Union Find) JAVA (0) | 2023.08.12 |