꾸꾸리

[BOJ/Python] 1043_거짓말 본문

Algorithm/BOJ

[BOJ/Python] 1043_거짓말

O773H 2023. 2. 11. 23:29
728x90

문제 출처:https://www.acmicpc.net/problem/1043

 

1043번: 거짓말

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

www.acmicpc.net

문제

지민이는 파티에 가서 이야기 하는 것을 좋아한다. 파티에 갈 때마다, 지민이는 지민이가 가장 좋아하는 이야기를 한다. 지민이는 그 이야기를 말할 때, 있는 그대로 진실로 말하거나 엄청나게 과장해서 말한다. 당연히 과장해서 이야기하는 것이 훨씬 더 재미있기 때문에, 되도록이면 과장해서 이야기하려고 한다. 하지만, 지민이는 거짓말쟁이로 알려지기는 싫어한다. 문제는 몇몇 사람들은 그 이야기의 진실을 안다는 것이다. 따라서 이런 사람들이 파티에 왔을 때는, 지민이는 진실을 이야기할 수 밖에 없다. 당연히, 어떤 사람이 어떤 파티에서는 진실을 듣고, 또다른 파티에서는 과장된 이야기를 들었을 때도 지민이는 거짓말쟁이로 알려지게 된다. 지민이는 이런 일을 모두 피해야 한다.

사람의 수 N이 주어진다. 그리고 그 이야기의 진실을 아는 사람이 주어진다. 그리고 각 파티에 오는 사람들의 번호가 주어진다. 지민이는 모든 파티에 참가해야 한다. 이때, 지민이가 거짓말쟁이로 알려지지 않으면서, 과장된 이야기를 할 수 있는 파티 개수의 최댓값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 사람의 수 N과 파티의 수 M이 주어진다.

둘째 줄에는 이야기의 진실을 아는 사람의 수와 번호가 주어진다. 진실을 아는 사람의 수가 먼저 주어지고 그 개수만큼 사람들의 번호가 주어진다. 사람들의 번호는 1부터 N까지의 수로 주어진다.

셋째 줄부터 M개의 줄에는 각 파티마다 오는 사람의 수와 번호가 같은 방식으로 주어진다.

N, M은 50 이하의 자연수이고, 진실을 아는 사람의 수는 0 이상 50 이하의 정수, 각 파티마다 오는 사람의 수는 1 이상 50 이하의 정수이다.

출력

첫째 줄에 문제의 정답을 출력한다.

예제 입력 1

4 3
0
2 1 2
1 3
3 2 3 4

예제 출력 1

3

예제 입력 2

4 1
1 1
4 1 2 3 4

예제 출력 2

0

예제 입력 3

4 1
0
4 1 2 3 4

예제 출력 3

1

예제 입력 4

4 5
1 1
1 1
1 2
1 3
1 4
2 4 1

예제 출력 4

2

예제 입력 5

10 9
4 1 2 3 4
2 1 5
2 2 6
1 7
1 8
2 7 8
1 9
1 10
2 3 10
1 4

예제 출력 5

4

예제 입력 6

8 5
3 1 2 7
2 3 4
1 5
2 5 6
2 6 8
1 8

예제 출력 6

5

예제 입력 7

3 4
1 3
1 1
1 2
2 1 2
3 1 2 3

예제 출력 7

0

풀이

 

M개의 파티 중에서 거짓말을 할 수 있는 파티의 수를 구하는 문제이다.

  • 진실은 아는 사람이 파티에 있다면 그 파티에서는 거짓말을 할 수 없다.
  • 그렇게 되면 그 파티에 있는 진실을 모르는 사람 또한 진실을 아는 사람 그룹에 포함된다.
  • 진실을 아는 사람이 전혀 없는 파티에서만 거짓말을 할 수 있다.

이러한 규칙을 가지고 Union & Find를 이용하여 다음과 같은 방법으로 문제를 해결하였다.

  1. 진실을 아는 사람들을 Union을 이용하여 하나의 집합으로 만든다.
  2. 각 파티마다 파티에 존재하는 사람들을 Union을 이용하여 하나의 집합으로 만든다.
  3. 또한 여기서 각 파티마다 한 명씩 뽑아 members라는 리스트에 저장한다.
  4. 2번 과정에서 만약 진실을 아는 사람이 존재한다면 모르는 사람들 또한 같은 집합에 속하게 될 것이다.
  5. 이 과정을 모든 파티에 대하여 수행한다.
  6. 이 과정이 끝나면 사람들은 진실을 아는 사람들과 아닌 사람들도 나뉘게 된다.
  7. 여기서 members에 있는 사람들을 Find를 이용하여 어떠한 집합에 속해있는지 확인하였을 때, 진실을 아는 사람들의 집합이 아닌 경우라면 count를 1 증가시킨다.
  8. 최종적으로 count의 값이 거짓말을 할 수 있는 파티의 수이다.

코드는 다음과 같다.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
import sys
 
def find_parent(parent,x):
    if x!=parent[x]:
        parent[x] = find_parent(parent,parent[x])
    return parent[x]
 
def union(parent, a,b):
    a = find_parent(parent,a)
    b = find_parent(parent,b)
 
    if a<b:
        parent[b] = a
    else:
        parent[a] = b
 
 
n,m = map(int,sys.stdin.readline().split())
parent = [i for i in range(n+1)]
know_people = list(map(int,sys.stdin.readline().split()))
 
party = []
for _ in range(m):
    party.append(list(map(int,sys.stdin.readline().split())))
 
if know_people[0==0:
    print(m)
else:
    for i in range(2,len(know_people)):
        union(parent,know_people[i-1],know_people[i])
 
    members = []
    for j in party:
        members.append(j[1])
        for k in range(2,j[0]+1):
            union(parent,j[k-1],j[k])
 
    count = 0
    for i in members:
        if find_parent(parent,i) != find_parent(parent,know_people[1]):
            count+=1
 
    print(count)
cs

 

 

728x90