1967_트리의 지름

hey hey·2022년 1월 2일
0

알고리즘

목록 보기
18/57
post-thumbnail

문제

트리(tree)는 사이클이 없는 무방향 그래프이다. 트리에서는 어떤 두 노드를 선택해도 둘 사이에 경로가 항상 하나만 존재하게 된다. 트리에서 어떤 두 노드를 선택해서 양쪽으로 쫙 당길 때, 가장 길게 늘어나는 경우가 있을 것이다. 이럴 때 트리의 모든 노드들은 이 두 노드를 지름의 끝 점으로 하는 원 안에 들어가게 된다.

이런 두 노드 사이의 경로의 길이를 트리의 지름이라고 한다. 정확히 정의하자면 트리에 존재하는 모든 경로들 중에서 가장 긴 것의 길이를 말한다.

입력으로 루트가 있는 트리를 가중치가 있는 간선들로 줄 때, 트리의 지름을 구해서 출력하는 프로그램을 작성하시오. 아래와 같은 트리가 주어진다면 트리의 지름은 45가 된다.

트리의 노드는 1부터 n까지 번호가 매겨져 있다.

입력

파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n-1개의 줄에 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 연결하는 두 노드 중 부모 노드의 번호를 나타내고, 두 번째 정수는 자식 노드를, 세 번째 정수는 간선의 가중치를 나타낸다. 간선에 대한 정보는 부모 노드의 번호가 작은 것이 먼저 입력되고, 부모 노드의 번호가 같으면 자식 노드의 번호가 작은 것이 먼저 입력된다. 루트 노드의 번호는 항상 1이라고 가정하며, 간선의 가중치는 100보다 크지 않은 양의 정수이다.

출력

첫째 줄에 트리의 지름을 출력한다.

풀이

  1. 1번에서 가장 먼 노드를 구한다.
  2. 그 노드에서 가장 멀리있는 노드를 구해준다.
  3. 그럼 그 길이가 가장 긴 지름이 된다.
import sys
sys.stdin = open('input.txt')
input = sys.stdin.readline
sys.setrecursionlimit(100000) 

N = int(input())
tree = [[]for _ in range(N+1)]

for _ in range(N-1):
    s,e,d = map(int,input().split())
    tree[s].append([e,d])   # 트리 양방향성
    tree[e].append([s,d])


length = 0      # 제일 긴길이 찾기
startpoint = 0  # 제일 긴길이의 노드번호  

def dfs(cnt,n):
    global length,startpoint
    visit[n]=1  # 방문을 해주고

    flag= True  # 이 노드에서 더이상 들어갈 곳이 없다 =True
    for e,d in tree[n]: # start-> end (distance)
        if visit[e]==0: # end 지점이 방문을 안햇으면
            dfs(cnt+d,e) # 들어가준다 
            flag=False   # 더 들어갔다 체크 
    
    if flag==True:      # 더이상 들어갈 곳이 없다면      
        if length<=cnt: # 가장 긴 길이가 맞는지 확인하고 
            length=cnt  # 바꿔준다
            startpoint = n  # 시작지점도 바꿔준다

visit=[0]*(N+1)     # 방문 체크용
dfs(0,1) # 1에서 가장 먼곳 찾는 dfs 

visit=[0]*(N+1) # 방문체크 초기화
dfs(0,startpoint)   # 찾은 노드에서 새롭게 찾기 
print(length)   # 가장 긴 길이 출력

오답

시간초과용 답안이다.
마지막 노드들을 다 찾아준 후에 그 값들을 모두 dfs를 돌려 찾으려고 했었다. 루트노드에서 가장 먼곳에서 시작해야 가장 긴 길이라는 사실이 필수인 문제!

import sys
sys.stdin = open('input.txt')
input = sys.stdin.readline

N = int(input())
tree_for_leaf = [[]for _ in range(N+1)]
tree = [[]for _ in range(N+1)]

for _ in range(N-1):
    s,e,d = map(int,input().split())
    tree_for_leaf[s].append([e,d])

    tree[s].append([e,d])
    tree[e].append([s,d])


def dfs_leaf(n):        # 리프노드 구하기
    if tree_for_leaf[n]:
        for e,d in tree_for_leaf[n]:
            dfs_leaf(e)
    else:
        leaf.append(n)

# 리프노드 구하기
leaf = []
dfs_leaf(1)
# print(leaf)
# [7, 8, 9, 10, 11, 12]

result=[]
def dfs(cnt,n):
    visit[n]=1
    flag =False
    for e,d in tree[n]:
        if visit[e] ==0:
            dfs(cnt+d,e)
            flag =True
    if flag==False:
        result.append(cnt)

while leaf:
    start = leaf.pop()
    visit = [0] * (N + 1)
    dfs(0,start)
print(max(result))
profile
FE - devp

0개의 댓글