b_트리의 지름_1967

source www.acmicpc.net/problem/1967
type 📌 개발노트
topics 600-알고리즘 & 코딩테스트 614 그래프
types 문제풀이
정답여부 모름

문제

트리에서 직선을만들려고할때 가장 길이가 긴것이몇인지
추후 자기노드를 통과하는 선을 지름이라고부르고
끝에서 자기노드까지를 반지름으로 표현예정

접근 : 밑부터 반지름들을 구해서 합하자

답 1(틀림)

자식 여부를 판별해서 자식이없는 leafnode부터 접근하느방법임
depth가 다른 leafnode가있을때 문제생김
자식노드다처리안됐는데 부모노드접근됨
ex ) answer has to be 13
input
5
1 2 3
1 3 3
2 4 5
2 5 7

import sys
import math
import heapq

NNum = int(sys.stdin.readline().strip())

parents = [None]* (NNum+1) # 자식입장에서 부모
sons = [[] for _ in range(NNum+1)] # 부모입장서자식
result = [0]  * (NNum+1)# 반
visited = [False] * (NNum+1)
output = -1

for _ in range(NNum-1):
    M,S,W=map(int,sys.stdin.readline().strip().split())
    parents[S]= M
    heapq.heappush(sons[M],(-W,S))


def findMaxLine():
    global parents,sons,result,visited,output
    empties = set([]) # leaf node
    for i in range(1,NNum+1):
        if len(sons[i]) < 1 and not visited[i]:
            empties.add(i)
            visited[i] = True
    if not empties:
        return

    print("leafnode",empties)
    filtered_moms = set([])
    # 각 leaf의 부모를 찾아
    for e in empties:
        if parents[e]:
            filtered_moms.add(parents[e])
    print("leafnode's mom",filtered_moms)
    if not filtered_moms:
        return

    # 각 부모의 최대 반지름과 지름을 구함
    for mom in filtered_moms:
        mysons= sons[mom]
        tmp = [] # 반, 지름
        while mysons and len(tmp)<2:
            w,s=heapq.heappop(mysons)
            if tmp:
                tmp.append(tmp[0]+result[s]-w)
            else:
                tmp.append(result[s]-w)
        print("노드의 최대 반지름과지름",mom,tmp)
        result[mom] = tmp[0]
        sons[mom] = []
        output = max(output,tmp[-1])
    return findMaxLine()
findMaxLine()
print(output)

답2(재귀 - 최대재귀깊이 초과)

https://dev-yyh.github.io/DataStructure/10
트리순회하는법찾다가 후위순회하면될거같다는 생각을함.
이미부모가 다처리된 자식노드를 돌 수있음
재귀를이용해서함 but 최대 재귀 깊이를 초과한다는 답을받음

import sys
import heapq

class Node:
    def __init__(self, data):
        self.data = data
        self.children = []


NNum = int(sys.stdin.readline().strip())
trees = [None]
weight = {}

for i in range(NNum):
    trees.append(Node(i+1))

# <span id="printtrees"></span>print(trees)
for _ in range(NNum-1):
    M,S,W=map(int,sys.stdin.readline().strip().split())
    trees[M].children.append(trees[S])
    weight[f"{M}-{S}"]=W

root = trees[1]
output = 0
# <span id="printweight"></span>print(weight)
def post_order_traversal(node):
    global output
    if node is None:
        return
    hq = []
    for child in node.children:
        pw = post_order_traversal(child)
        w = weight[f"{node.data}-{child.data}"]
        # print(node.data,"<-",child.data,":",pw+w)
        heapq.heappush(hq,-(pw+w))
    tmp = [output]
    try:
        w1 = heapq.heappop(hq)
        tmp.append(-w1)
        w2 = heapq.heappop(hq)
        tmp.append(-(w1+w2))
    except:
        pass
    output = max(tmp)
    # print(node.data,":",output)
    try:
        return tmp[1]
    except:
        return 0
    

post_order_traversal(root)
print(output)

답3(정답)

그래서 재귀를 while과 stack을 이용하여 구현함
재귀(콜백)은 스택으로 구현가능(컴터에서내부적으로도그렇게실행됨ㅋ)

import sys
import heapq

class Node:
    def __init__(self, data):
        self.data = data
        self.children = []

NNum = int(sys.stdin.readline().strip())
trees = [None]
weight = {}

for i in range(NNum):
    trees.append(Node(i+1))

for _ in range(NNum-1):
    M,S,W = map(int, sys.stdin.readline().strip().split())
    trees[M].children.append(trees[S])
    weight[f"{M}-{S}"] = W

root = trees[1]
output = 0

def post_order_iterative(root):
    global output
    stack = [(root, 0, [])]  # (현재노드, 다음 방문할 자식 인덱스, 자식별 반환값 리스트)
    while stack:
        node, idx, results = stack.pop()
        if idx < len(node.children):
            stack.append((node, idx + 1, results))
            stack.append((node.children[idx], 0, []))
        else:
            hq = []
            for i, child_val in enumerate(results):
                w = weight[f"{node.data}-{node.children[i].data}"]
                heapq.heappush(hq, -(child_val + w))
            tmp = [output]
            try:
                w1 = heapq.heappop(hq)
                tmp.append(-w1)
                w2 = heapq.heappop(hq)
                tmp.append(-(w1 + w2))
            except:
                pass
            output = max(tmp)
            ret_val = tmp[1] if len(tmp) > 1 else 0

            if stack:
                stack[-1][2].append(ret_val)

post_order_iterative(root)
print(output)