1967. 트리의 지름 본문
문제링크 : https://www.acmicpc.net/problem/1967
<입력>
노드의 개수 n
(n-1)개의 간선 정보 (부모, 자식, 가중치)
<출력>
트리의 지름(트리의 두 정점 간의 거리 중 가장 최대값)
<풀이>
우선, 트리의 가중치가 음수 혹은 0인 경우가 존재하지 않는다면 두 정점간의 거리의 최대값은 리프 - 리프 노드 사이에 존재한다.
이 생각을 시작으로 문제를 접근했다.
루트 노드의 번호는 언제나 1이다.
이 문제는 부분으로 나눌 수 있다.
6번 노드가 루트인 서브 트리의 최대값은 (10+6=16)이고 5번 노드가 루트인 서브 트리의 최대값은 (15+4=19)이다.
그리고 각각 위로 갈 수 있는 최대 경로인 10과 15를 넘겨준다.
다음으로 3번 노드가 루트인 서브트리의 최대값은 5번 노드로부터 받은 (15+11=26), 6번 노드로부터 받은 (10+9=19)의 합인 (26+19=45)가 된다.
그렇게 각 노드의 서브트리의 최대값을 저장하면서 최종 루트인 1에 도달할 때까지 연산을 수행한 다음 가장 큰 값을 찾는다면 해결할 수 있다.
위 트리를 예시로 진행한다면 아래 그림과 같다.
- 소스 코드 -
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #include<iostream> #include<vector> #include<algorithm> using namespace std; typedef struct Edge{ int parent; // 부모 노드 int parent_weight; // 부모와 자신간의 간선의 가중치 int cur_maximum; // 위로 넘겨주는 값이 아닌 현재 노드에서의 최대값 int index; // 현재 노드의 인덱스 번호(curNode 값 갱신하기 위함) vector<int> son; // 자식 배열 Edge(){ parent=0; parent_weight=0; cur_maximum=0; index=0; } }E; E edges[10002]; // 엣지를 저장합니다. int maximum[10002]; // 노드별 최대값을 저장하기 위한 배열 int solve(E curEdge){ // bfs if(curEdge.son.empty()){ // 리프노드일 경우 부모와의 간선 가중치를 리턴 return curEdge.parent_weight; } int maximum1=0; // 최대값 1번(제일 큰) int maximum2=0; // 최대값 2번(2번째로 큰) for(auto it:curEdge.son){ int temp=solve(edges[it]); if(temp>maximum1){ maximum2=maximum1; maximum1=temp; }else if(temp==maximum1){ maximum2=temp; }else if(temp>maximum2){ maximum2=temp; } // 모든 자식 노드에 대해 경로의 최대값을 구한다. // 자식 노드가 1개일 경우 나머지는 0으로 초기화되므로 걱정 X } maximum[curEdge.index]=maximum1+maximum2; // 현재 노드가 루트인 서브트리의 지름 return maximum1+curEdge.parent_weight; // 최대값과 부모와의 거리를 더해서 부모에게 리턴 } int main(void){ int n; scanf("%d",&n); // 입력 받기 for(int i=1;i<n;i++){ int p,s,w; scanf("%d %d %d",&p,&s,&w); edges[p].son.push_back(s); edges[s].parent=p; edges[s].parent_weight=w; edges[s].index=s; } // solve 함수를 이용해 bfs를 수행하며 최대값 배열 채우기 int result=0; result=solve(edges[1]); // 최대값 배열에서 최대값 찾기 // 루트에서 최대일 경우 0번 인덱스에 값이 채워지므로 0번부터 확인 for(int i=0;i<=n;i++){ result=max(maximum[i],result); } printf("%d\n",result); } | cs |
'알고리즘 문제풀기 > 백준(Acmicpc)' 카테고리의 다른 글
14720. 우유 축제 (0) | 2019.01.15 |
---|---|
11727. 2×n 타일링 2 (0) | 2019.01.15 |
1008. A/B (0) | 2018.12.30 |
3111. 검열 ( 오답노트 ) (0) | 2018.12.20 |
16510. Predictable Queue (0) | 2018.11.30 |
Comments