문제 풀이/백준

백준 - 거짓말 (1043) [C++]

JJJaewon 2024. 1. 22. 18:58
반응형

이 문제는 구현으로 풀었다. 문제 카테고리를 보면 분리 집합, 그래프 등이 나오는데 입력 크기가 작아 구현으로도 풀렸다.

 

이 문제의 핵심은 진실을 아는 사람이 한명이라도 있는 파티에서는 진실을 말할 수 밖에 없고, 그 파티에 참가한 모든 사람이 진실을 알게 된다는 것이다.

 

그러나 위의 핵심을 가지고 풀어도 정답이 나오지 않을 때가 있는데, 이는 진실을 알고 있는 사람이 입력 마지막에 전부 몰려있는 경우이다. 이 경우 파생되는 인원들을 제대로 체크하지 않고 넘어갈 수 있기 때문이다.

 

그래서 진실을 알고 있는 사람들을 마킹하는 함수를 M번 반복하여 정답을 찾을 수 있었다. 만약 파티가 10개이고, 맨 마지막에만 진실을 알고 있는 사람이 있는 파티가 존재한다고 가정하면 최악의 경우 각 루프마다 한명씩 추가가 되기 때문에 최대 M번을 반복하여 확실하게 검증할 수 있다.

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

#define MAX 50

int N, M;
int knowTruthCount;
bool knowTruth[MAX + 1];
vector<int> party[MAX];

bool isBaseCase() {
	if (knowTruthCount == 0) {
		cout << M << '\n';

		return true;
	}

	return false;
}

void input() {
	cin >> N >> M;
	cin >> knowTruthCount;

	for (int i = 0; i < knowTruthCount; i++) {
		int num;
		cin >> num;

		knowTruth[num] = true;
	}

	for (int i = 0; i < M; i++) {
		int cnt;
		cin >> cnt;

		for (int j = 0; j < cnt; j++) {
			int num;
			cin >> num;

			party[i].push_back(num);
		}
	}
}

bool isContainsTruth(const vector<int>& tempParty) {
	for (int num : tempParty) {
		if (knowTruth[num]) {
			return true;
		}
	}

	return false;
}

void makeAllTruth(const vector<int>& tempParty) {
	for (int num : tempParty) {
		knowTruth[num] = true;
	}
}

void allPossibleTruth() {
	for (int i = 0; i < M; i++) {
		const vector<int> presentParty = party[i];

		if (isContainsTruth(presentParty)) {
			makeAllTruth(presentParty);
		}
	}
}

int solve() {
	for (int i = 0; i < M; i++) {
		allPossibleTruth();
	}

	int result = 0;
	for (int i = 0; i < M; i++) {
		vector<int> presentParty = party[i];

		if (!isContainsTruth(presentParty)) {
			result++;
		}
	}

	return result;
}

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

	input();

	if (isBaseCase()) {
		return 0;
	}

	cout << solve() << '\n';
	
	return 0;
}
반응형