일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 내란죄
- 오블완
- ccw
- 윤석열 내란수괴
- 내란수괴
- 이분 탐색
- 다익스트라
- LCA
- Prim
- 알고리즘
- Python
- 비상계엄
- 프림
- 파비우스 전략
- dfs 백트래킹
- 분할정복
- 투 포인터
- 윤석열
- dfs
- BFS
- 구조론
- DP
- 왈왈왈
- 티스토리챌린지
- 내란수괴 윤석열
- 유니온 파인드
- 국민의 힘 뿌리
- union find
- 재귀함수
- 백준
- Today
- Total
Toolofv 님의 블로그
[Python] 백준 1949 - 우수 마을 본문
문제
N개의 마을로 이루어진 나라가 있다. 편의상 마을에는 1부터 N까지 번호가 붙어 있다고 하자. 이 나라는 트리(Tree) 구조로 이루어져 있다. 즉 마을과 마을 사이를 직접 잇는 N-1개의 길이 있으며, 각 길은 방향성이 없어서 A번 마을에서 B번 마을로 갈 수 있다면 B번 마을에서 A번 마을로 갈 수 있다. 또, 모든 마을은 연결되어 있다. 두 마을 사이에 직접 잇는 길이 있을 때, 두 마을이 인접해 있다고 한다.
이 나라의 주민들에게 성취감을 높여 주기 위해, 다음 세 가지 조건을 만족하면서 N개의 마을 중 몇 개의 마을을 '우수 마을'로 선정하려고 한다.
- '우수 마을'로 선정된 마을 주민 수의 총 합을 최대로 해야 한다.
- 마을 사이의 충돌을 방지하기 위해서, 만일 두 마을이 인접해 있으면 두 마을을 모두 '우수 마을'로 선정할 수는 없다. 즉 '우수 마을'끼리는 서로 인접해 있을 수 없다.
- 선정되지 못한 마을에 경각심을 불러일으키기 위해서, '우수 마을'로 선정되지 못한 마을은 적어도 하나의 '우수 마을'과는 인접해 있어야 한다.
각 마을 주민 수와 마을 사이의 길에 대한 정보가 주어졌을 때, 주어진 조건을 만족하도록 '우수 마을'을 선정하는 프로그램을 작성하시오.
입력
첫째 줄에 정수 N이 주어진다. (1 ≤ N ≤ 10,000) 둘째 줄에는 마을 주민 수를 나타내는 N개의 자연수가 빈칸을 사이에 두고 주어진다. 1번 마을부터 N번 마을까지 순서대로 주어지며, 주민 수는 10,000 이하이다. 셋째 줄부터 N-1개 줄에 걸쳐서 인접한 두 마을의 번호가 빈칸을 사이에 두고 주어진다.
출력
첫째 줄에 '우수 마을'의 주민 수의 총 합을 출력한다.
문제해결방법 -
1. 바로 이전 문제가 더 어려운데, 같은 패턴으로 DFS + DP 로 구현한다.
2. DFS는 가장 끝에서, 그러니까 더이상 자식노드가 없을 때까지 재귀함수로 파고들어가다 차례차례 리턴을 하게 된다. 그 순서대로 DP를 구성하는 게 가능하다.
1) DP[x][0] += DP[next][1] -> 도시(x)를 선택했을 때, 그 전 도시(next)는 선택할 수 없다.
2) DP[x][1] += max(DP[next]) -> 도시(x)를 선택하지 않았을 때, 그 전 도시(next)의 최댓값 인구수를 더해준다.
DFS(x)일 때,
그 전 도시(next)까지의 최댓값 우수 마을은 ◆ - ◇ 혹은 ◇ - ◆ 이라고 한다면,
도시(x)가 선택되었다면 ◆ - ◇ - ◆
도시(x)가 선택되지 않았다면 ◇ - ◇ - ◆, ◇ - ◆ - ◇ 둘중 하나의 최댓값이다. 여기서 앞의 경우( ◇ - ◇ - ◆ )에서 선택되지 않는 마을이 이중으로 나와 안된다고 생각하기 쉬운데, 만약 그 경우가 최댓값이라면 다음 DFS(x의부모)일 때, ◆ - ◇ - ◇ - ◆ 이 되기 때문에 문제의 3. 항목과 위배되지 않는다는 걸 알 수 있다.
- DFS + DP
import sys
sys.setrecursionlimit(10**6)
input = sys.stdin.readline
n = int(input())
citizen = [0]+list(map(int, input().split()))
city = [[] for _ in range(n+1)]
v = [0 for _ in range(n+1)]
dp = [[0, 0] for _ in range(n+1)]
for _ in range(n-1):
a, b = map(int, input().split())
city[a].append(b)
city[b].append(a)
def dfs(x):
v[x] = 1
dp[x][0] = citizen[x]
dp[x][1] = 0
for next in city[x]:
if v[next] == 0:
dfs(next)
dp[x][0] += dp[next][1] # 도시 x 선택
dp[x][1] += max(dp[next]) # 도시 x 미선택일 때 최댓값
dfs(1)
print(max(dp[1]))
'Algorithm' 카테고리의 다른 글
[Python] 백준 - 6549 히스토그램에서 가장 큰 직사각형 (2) | 2024.07.23 |
---|---|
[Python] 백준 - 25308 방사형 그래프 (3) | 2024.07.20 |
[Python] 백준 - 2213 트리의 독립집합 (0) | 2024.07.15 |
[Python] 백준 - 1992 쿼드트리 (0) | 2024.07.12 |
[Python] 백준 - 15681 트리와 쿼리 (0) | 2024.07.11 |