티스토리 뷰

java/BAEKJOON

java 1034번 거짓말 (백준)

rofn123 2023. 3. 19. 15:30
import java.util.Scanner;

class Main {
	static int find(int p[], int x) { //노드가 속한 부분집합의 대표 노드를 찾는 함수
		if(p[x] == x) return x;
		return p[x] = find(p, p[x]);
	}
	
	static void merge(int p[], int x, int y) {//두개의 노드의 부분집합을 합치는 함수
		x = find(p, x);
		y = find(p, y);
		if(x!=y) p[x] = y;
		return;
	}
	
	static boolean same(int p[], int x, int y) {//두개의 노드가 같은 부분집합인지를 찾는 함수
		x = find(p, x);
		y = find(p, y);
		return x == y;
	}
	
	
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n, m, s, tmp, ans=0;
		n = scan.nextInt();
		m = scan.nextInt();
		s = scan.nextInt();
		
		int p[] = new int[n+1];//대표노드를 저장할 배열
		for(int i=0; i<=n; i++) p[i]=i; //처음엔 각각의 노드의 집합의 대표노드는 자기자신
		int save[][] = new int[m][n+1]; //간선? 파티를 저장할 배열
		
		for(int i=0; i<s; i++) {//파티 정보 입력 받기
			tmp = scan.nextInt(); //나의 진실을 아는 사람들은
			merge(p, 0, tmp);//나와 같은 집합에 있는 것과 같다.
		}
		
		for(int i=0; i<m; i++) {//파티 정보 입력 받기
			int a, b=0, j;
			a = scan.nextInt();
			for(j=0; j<a; j++) {
				tmp = scan.nextInt();
				if(b>0) merge(p, b, tmp);//같은 파티에 있는 사람들은 같은 집합에 있다고 볼 수 있다.
				save[i][j] = tmp;//파티를 배열로 저장
				b=tmp;
			}
			save[i][j] = 0;
		}
		
		for(int i=0; i<m; i++) {//저장했던 파티의 내용을 가지고, 내가 과장을 할 수 있는 파티의 개수를 찾기
			int j = 0;
			while(true) {
				if(save[i][j] == 0) ans++;//파티에 참석한 사람이 나와 같은 집합이 아니라면, 나는 과장을 할 수 있다.
				if(same(p, 0, save[i][j])) break;//만약 나와 같은 집합이라면, 나의 진실을 아므로, 그 파티에선 과장을 할 수 없다.
				j++;
			}
		}
		
		System.out.print(ans);
		scan.close();
	}
}

 

풀이 : union(합집합) + find(찾기)

 

1. 각 사람들의 부분집합의 대표노드를 자기 자신으로한 배열을 만든다.

 

2. 나를 알고 있는 사람들은 나와 같은 부분집합에 있는 것으로 본다.

 

3. 파티에서 같이 참석한 사람들은 같은 부분집합에 있는 것으로 본다.

만약 A는 날 알고 B는 날 모른다 해도, 나는 B에게만 과장을 할 수 없기때문이다. (A와 B는 같은 파티에 있으니)

또한 만약 이전에 파티는 B만 참석했다고 해도 과장을 할 수가 없게 된다.

왜냐하면, B만 있을 때는 과장 했다가, A B가 있는 파티에서 진실만을 말하게 되면, 결국 B는 내가 전에는 과장을 하였음을 알 수 있기 때문이다. 따라서 파티에 같이 참여하는 사람들은 같은 집합으로 묶어준다.

 

4. 3.의 과정을 하는 동안 입력 받은 파티의 정보를 따른 배열에다가 저장해 둔다.

 

5. 저장한 파티의 정보를 가지고, 파티에 자신과 같은 집합인 사람이 없다면 과장이 가능한 파티이며, 이러한 파티가 몇개인지를 구한다.

 

6. 과장이 가능한 파티의 개수를 출력한다.

 

https://h202.tistory.com/241

 

c언어 1034번 거짓말 (백준)

#include #include int find(int p[], int x) { //노드가 속한 부분집합의 대표 노드를 찾는 함수 if(p[x] == x) return x; return p[x] = find(p, p[x]); } void merge(int p[], int x, int y) {//두개의 노드의 부분집합을 합치는 함수

h202.tistory.com

위의 c언어 코드를 java로 바꾸었습니다.

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함