본문 바로가기

백준 문제 풀이

백준 1043번 - 거짓말(C++)

728x90

https://www.acmicpc.net/problem/1043

 

1043번: 거짓말

지민이는 파티에 가서 이야기 하는 것을 좋아한다. 파티에 갈 때마다, 지민이는 지민이가 가장 좋아하는 이야기를 한다. 지민이는 그 이야기를 말할 때, 있는 그대로 진실로 말하거나 엄청나게

www.acmicpc.net

 

 처음 봤을 땐 브루트포스로 전부 확인하는 형식으로 풀었는데 3%에서 틀렸습니다가 발생했다.

그래프 문제라고는 상상을 못했다. 정확히는 유니온 파인드 문제였다. 유니온 파인드 알고리즘은 정확히 공부한 적이 없는데 이번에 공부할 수 있었다.

 

1. 먼저 각 진실을 알고 있는 자들의 유니온(집합) 번호를 0번으로 지정한다.

2. 파티를 열고 파티를 들어온 1번 사람들과 이후 사람들을 합쳐준다.

3. 이후 각 파티를 다시 돌며 몇개의 파티에서 과장이 가능한지 체크한다.

 

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;

int N, M, K;
int root[51];

int u_find(int x) {
	if (root[x] == x) return x;
	else return root[x] = u_find(root[x]);
}
void Union(int x, int y) {
	int rootx = u_find(x);
	int rooty = u_find(y);

	if (rootx != rooty) {
		if (rootx < rooty)
			root[rooty] = rootx;
		else
			root[rootx] = rooty;
	}
}



int main() {
	ios_base::sync_with_stdio(NULL);
	cin.tie(0);

	cin >> N >> M;

	for (int i = 1; i <= N; i++) {
		root[i] = i;
	}
	
	cin >> K;

	for (int i = 0; i < K; i++) {
		int tmp;
		cin >> tmp;
		root[tmp] = 0;
	}

	int party[51][51];
	int partyNum[51];

	for (int i = 0; i < M; i++) {
		cin >> partyNum[i];
		cin >> party[i][0];
		//cout << party[i][0] << endl;
		for (int j = 1; j < partyNum[i]; j++) {
			cin >> party[i][j];
			Union(party[i][0], party[i][j]);
		}
	}

	int answer = M;

	for (int i = 0; i < M; i++) {
		for (int j = 0; j < partyNum[i]; j++) {
			//cout << party[i][j] << " " << u_find(root[party[i][j]]) << endl;
			if (u_find(root[party[i][j]]) == 0) {
				answer--;
				break;
			}
		}
	}

	cout << answer << '\n';
}

'백준 문제 풀이' 카테고리의 다른 글

백준 2252번 줄세우기 (C++)  (0) 2023.08.22
백준 14391번 종이 조각 (C++)  (0) 2023.08.12
백준 1253번 좋다(C++)  (0) 2023.07.31
백준 17144번 미세먼지여 안녕!(C++)  (0) 2023.07.30
백준 10407번 2 타워(C++)  (0) 2023.07.23