BOJ 백준 1289 : 트리의 가중치
Updated:
시작하면서
이번 문제는 트리(Tree) 의 속성과 관련된 문제이다.
문제 이해
이 문제에서는 용어 2개를 정의한다.
- 경로의 가중치 : 경로에 해당하는 간선의 곱
- 트리의 가중치 : 트리 상에 가능한 모든 경로에 대해 경로의 가중치의 합
이 문제의 최대 트리 정점 개수가 100,000개이므로, 단순히 전부 계산하는 O(N^2)의 방식으로 문제를 풀려고 접근하면 시간 초과가 발생한다. 트리의 특성상 사이클이 존재하지 않으므로 한 번에 전부 순회하는 방식으로 O(N)의 시간 복잡도로 문제를 풀어야함을 예상해 볼 수 있다.
그런데 여기까지만 생각하고 문제를 풀지 못했다. 구글링을 통해 검색한 결과 공식을 만들어냈어야 했는데 해당 부분에 대한 접근이 부족했다. 참고한 블로그 링크를 남긴다.
해결
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define DIVIDE_NUMBER (1000000007)
class info
{
public:
int previousNode;
int currentNode;
int routeWeight;
};
long long FindPath(const vector<vector<pair<int, int>>>& graph, long long &result, int currentNode, int previousNode)
{
long long multiply = 1;
for (int i = 0; i < graph[currentNode].size(); i++)
{
int nextNode = graph[currentNode][i].first;
int weight = graph[currentNode][i].second;
if (nextNode == previousNode)
{
continue;
}
long long subTreeResult = FindPath(graph, result, nextNode, currentNode) * weight % DIVIDE_NUMBER;
result += (subTreeResult * multiply) % DIVIDE_NUMBER;
result %= DIVIDE_NUMBER;
multiply = (multiply + subTreeResult) % DIVIDE_NUMBER;
}
return multiply;
}
int main()
{
// sync off
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// sync off
vector<vector<pair<int, int>>> graph;
int N;
cin >> N;
graph.resize(N + 1);
for (int i = 0; i < N - 1; i++)
{
int A, B, W;
cin >> A >> B >> W;
graph[A].push_back(make_pair(B, W));
graph[B].push_back(make_pair(A, W));
}
long long result = 0;
FindPath(graph, result, 1, 0);
cout << result % DIVIDE_NUMBER;
return 0;
}
Leave a comment