백준 13325번 - 이진 트리 🌲
🔗 문제 링크: https://www.acmicpc.net/problem/13325
13325번: 이진 트리
이진 트리의 간선 가중치를 최소로 조절해 모든 리프 노드 경로 가중치를 동일하게 만드는 문제입니다.
www.acmicpc.net
📝 문제 요약
- 높이 N의 완전 이진 트리에서 루트부터 리프까지의 경로의 가중치 합이 모두 같도록 만드려고 합니다.
- 각 간선의 초기 가중치가 주어지며, 일부 간선의 가중치를 증가시킬 수 있습니다.
- 모든 리프 노드까지의 경로 가중치 합이 동일해지도록 하기 위한 최소의 증가 비용을 출력합니다.
🧷 문제 분류
- 트리
- 누적합
📦 제출 정보
🔗 소스코드: GitHub - cbkpar/BOJ/boj_13325.cpp
제출 번호 | 아이디 | 문제 | 결과 | 메모리 | 시간 | 언어 | 코드 길이 |
---|---|---|---|---|---|---|---|
93910521 | cbkpar | 13325 | 맞았습니다!! | 18408 KB | 144 ms | C++17 | 978 B |
💻 코드 (C++)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int iN;
cin >> iN;
int iTotal = 0;
for (int i = 1; i <= iN; ++i)
{
iTotal += 1 << i;
}
iTotal += 2;
long long lAns = 0;
vector<long long> vecNum(iTotal, 0);
for (int i = 2; i < iTotal; ++i)
{
cin >> vecNum[i];
lAns += vecNum[i];
}
long long lMax = 0;
for (int i = 2; i < iTotal; ++i)
{
int iNext = i * 2;
if (iNext >= iTotal)
{
lMax = max(lMax, vecNum[i]);
continue;
}
vecNum[iNext] += vecNum[i];
vecNum[iNext + 1] += vecNum[i];
}
for (int i = iTotal - 1; i >= 2; --i)
{
if (i * 2 >= iTotal)
{
vecNum[i] = lMax - vecNum[i];
continue;
}
vecNum[i] = min(vecNum[i * 2], vecNum[i * 2 + 1]);
vecNum[i * 2] -= vecNum[i];
vecNum[i * 2 + 1] -= vecNum[i];
}
for (int i = 2; i < iTotal; ++i)
{
lAns += vecNum[i];
}
cout << lAns << "\n";
return 0;
}
💡 풀이 방법
🔍 문제 접근
- 루트 노드부터 각 리프 노드까지의 경로의 가중치 최대값 계산 후 다른 경로의 부족한 부분만큼 보정.
- 각 노드에서 자식 노드로 누적합을 전파하고, 자식에서 부모방향으로 차이를 보정해주며 최소 증가량을 계산.
🧠 핵심 아이디어
- 전방 탐색을 통해 자식에게 누적합을 전파한 후, 경로에 부족한 값을 역으로 채워주는 방식.
- 모든 경로 중 가장 큰 누적합을 기준으로 남은 간선 가중치를 계산하고 누적합니다.
⚙️ 구현 방식
- 트리의 간선 수는
2N+1 - 2
개이므로 이만큼 입력을 받아 vector에 저장합니다. - 자식 노드로 누적합을 더해주며 최대 경로 길이를 계산합니다.
- 계산 된 밑에서 위로 올라가면서 필요한 가중치의 값을 구한다.
✅ 시간 복잡도
- 트리 탐색은 O(N)이며, 완전 이진 트리의 노드 수는
2N+1 - 1
이므로 충분히 빠르게 수행됩니다.
🧪 예제 입력 / 출력
📘 예제 1
입력
2
2 2 2 1 1 3
출력
15
📙 예제 2
입력
1
1 1000
출력
2000
📘 예제 3
입력
3
1 2 1 3 2 4 1 1 1 1 1 1 1 1
출력
27
📙 예제 4
입력
2
1 1000 1 1 1000 1000
출력
5001