Skip to content

Conversation

@g0rnn
Copy link
Collaborator

@g0rnn g0rnn commented Aug 21, 2025

πŸ”— 문제 링크

트리의 지름

βœ”οΈ μ†Œμš”λœ μ‹œκ°„

1h

✨ μˆ˜λ„ μ½”λ“œ

사싀 ν•œμ‹œκ°„ κΉŒμ§„ 걸리진 μ•Šκ³ , μ†”λ£¨μ…˜μ„ μƒκ°λ§Œ ν•œλ‹€λ©΄ 금방 ν’€ 수 μžˆλŠ” λ¬Έμ œμž…λ‹ˆλ‹€.

μš°μ„  μ˜€ν•΄ν•˜λ©΄ μ•ˆλ κ²ƒμ΄ "트리의 κ°œλ…"μž…λ‹ˆλ‹€. νŠΈλ¦¬λŠ” μ–΄λ–€ 쑰건을 κ°€μ§„ κ·Έλž˜ν”„μž…λ‹ˆλ‹€.

image
  1. κ°„μ„ μ˜ κ°œμˆ˜λŠ” N-1개
  2. 사이클이 μ—†μŒ
  3. λ”°λΌμ„œ μž„μ˜μ˜ 두 λ…Έλ“œ κ°„ κ²½λ‘œλŠ” 였직 ν•˜λ‚˜!

이 사싀을 κΉ¨λ‹«λŠ”λ‹€λ©΄ μ†”λ£¨μ…˜μ΄ κ½€λ‚˜ μ‰½κ²Œ λ– μ˜€λ₯Όμ§€λ„ λͺ¨λ¦…λ‹ˆλ‹€.

문제λ₯Ό ν‘ΈλŠ” 방법은 일단 μž„μ˜μ˜ λ…Έλ“œλ‘œλΆ€ν„° κ°€μž₯ λ¨Ό 거리의 λ…Έλ“œλ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€. 그리고 κ·Έ λ…Έλ“œλ‘œλΆ€ν„° λ‹€λ₯Έ λ…Έλ“œκΉŒμ§€μ˜ 거리 쀑 κ°€μž₯ 큰 값을 μ°ΎλŠ”κ±°μ£ .

image

그림을 보면 μ’€ 더 μ‰½κ²Œ 이해가 κ°€λŠ₯ν•©λ‹ˆλ‹€. μž„μ˜μ˜ λ…Έλ“œλ‘œλΆ€ν„° κ°€μž₯ 멀리 λ–¨μ–΄μ ΈμžˆλŠ” λ…Έλ“œλŠ” 단 1개 μž…λ‹ˆλ‹€. 이 5번 λ…Έλ“œλ‘œλΆ€ν„° κ°€μž₯ 멀리 λ–¨μ–΄μ ΈμžˆλŠ” λ…Έλ“œλ₯Ό 찾으면? 그건 트리의 지름이 되겠죠.

πŸ“š μƒˆλ‘­κ²Œ μ•Œκ²Œλœ λ‚΄μš©

dfs둜 λ°©λ¬Έν•  λ•Œ 미리 visited = true둜 μ„€μ •ν•˜λ©΄ μ•ˆλœλ‹€!!

μ œκ°€ 1μ‹œκ°„μ΄λ‚˜ 써버린 μ΄μœ μž…λ‹ˆλ‹€. visitedλ₯Ό λ…Έλ“œμ— λ°©λ¬Έν•˜κΈ°μ „ true둜 μ„€μ •ν•˜λ©΄ λ‹€μŒ λ…Έλ“œλ₯Ό λ°©λ¬Έν•  λ•Œ λ¬Έμ œκ°€ λ°œμƒν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 직관적인 이해가 λ˜μ§„ μ•ŠμœΌλ‚˜ μ˜ˆμ „μ—λ„ 같은 문제둜 μ‹œκ°„μ„ 썼던 기얡이 λ‚©λ‹ˆλ‹€. μ‘°μ‹¬ν•˜μ‹œκΈΈ λ°”λžλ‹ˆλ‹€.!

private static void dfs(int node, int len) {
        if (len > max) {
            max = len;
            endNode = node;
        }
        for (int[] next : tree.get(node)) {
            if (visited[next[0]]) continue;
            visited[next[0]] = true;
            dfs(next[0], len + next[1]);
        }
    }

μœ„μ²˜λŸΌ dfsλ₯Ό μ‹€ν–‰ν•˜κΈ° μ „ visited = true둜 돌리면 μœ„ν—˜ν•©λ‹ˆλ‹€! 이 λ¬Έμ œμ—μ„œ λ°©λ¬Έ ν‘œμ‹œλ₯Ό dfs전에 ν•˜κ³  μ‹Άλ‹€λ©΄ max 값을 λ‘λ²ˆμ§Έ dfsμ‹€ν–‰ν•˜κΈ° 전에 μ΄ˆκΈ°ν™”ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€. κΆκΈˆν•˜λ‹€λ©΄ μ•„λž˜ μ½”λ“œλ₯Ό μ°Έκ³ ν•΄λ³΄μ„Έμš©

warning
import java.io.*;
import java.util.*;

public class Main {

    static int v;
    static List<List<int[]>> tree = new ArrayList<>();
    static int endNode, max = -1;
    static boolean[] visited;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        v = Integer.parseInt(br.readLine());
        for (int i = 0; i <= v; i++) {
            tree.add(new ArrayList<>());
        }
        for (int i = 0; i < v; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            int cur = Integer.parseInt(st.nextToken());
            while (true) {
                int u = Integer.parseInt(st.nextToken());
                if (u == -1) break;
                int cost = Integer.parseInt(st.nextToken());
                tree.get(cur).add(new int[]{u, cost});
            }
        }
        br.close();

        visited = new boolean[v + 1];
        visited[0] = true;
        //max = -1;
        dfs(1, 0);

        visited = new boolean[v + 1];
        visited[endNode] = true;
        max = -1;
        dfs(endNode, 0);

        System.out.println(max);
    }

    private static void dfs(int node, int len) {
        if (len > max) {
            max = len;
            endNode = node;
        }
        for (int[] next : tree.get(node)) {
            if (visited[next[0]]) continue;
            visited[next[0]] = true;
            dfs(next[0], len + next[1]);
        }
    }
}

@g0rnn g0rnn self-assigned this Aug 21, 2025
Copy link
Collaborator

@kokeunho kokeunho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

트리의 지름을 μ°ΎλŠ” 법을 배울 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

μž„μ˜μ˜ μ •μ μ—μ„œ κ°€μž₯ λ¨Ό 지점을 찾은 ν›„,
κ·Έ μ§€μ μ—μ„œ κ°€μž₯ λ¨Ό μ§€μ κΉŒμ§€μ˜ 거리가 지름이 λœλ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
μ§κ΄€μ μœΌλ‘œ 이해가 λ˜μ§€ μ•Šμ•„ λ‚©λ“ν•˜λŠ”λ° μ‹œκ°„μ΄ μ’€ κ±Έλ Έλ„€μš”.

μ €μ˜ 처음 ν’€μ΄λŠ” (λ°©ν–₯ κ·Έλž˜ν”„λŠ” μ•„λ‹ˆμ§€λ§Œ) μ •μ λ§ˆλ‹€ μ§„μž… κ°„μ„ μ˜ 수λ₯Ό μ„Έκ³ 
κ°€μž₯ λ§Žμ€ μ§„μž… 간선을 κ°€μ§„ μ •μ μ—μ„œ
κ°€μž₯ λ¨Ό 거리와 두 번째둜 λ¨Ό 거리λ₯Ό ν•©ν•˜λ©΄ 지름이 λ˜μ§€ μ•Šμ„κΉŒ μƒκ°ν•˜μ—¬ ν’€μ—ˆμŠ΅λ‹ˆλ‹€.

λ­”κ°€ μ• λ§€ν•˜λ‹€κ³  생각은 ν–ˆμ§€λ§Œ
μ˜ˆμ‹œ μž…λ ₯에 λŒ€ν•΄μ„œ μ •λ‹΅μ˜ 좜λ ₯이 λ‚˜μ˜€κΈΈλž˜ λ§žλŠ” 쀄 μ•Œμ•˜μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ 이런 경우 κ°€μž₯ λ¨Ό λ…Έλ“œκΉŒμ§€μ˜ κ²½λ‘œμ™€ 두 번째둜 λ¨Ό λ…Έλ“œκΉŒμ§€μ˜ κ²½λ‘œκ°€
μ„œλ‘œ λ‹€λ₯Έ λ°©ν–₯으둜 λ»—μ–΄κ°€λŠ” κ²½λ‘œλΌλŠ” 보μž₯이 μ—†κΈ° λ•Œλ¬Έμ— μ˜ˆμ™Έ 상황이 λ°œμƒν•©λ‹ˆλ‹€.

μˆ˜κ³ ν•˜μ…¨μŠ΅λ‹ˆλ‹€!

Details

import java.io.*;
import java.util.*;

public class Main {
    static int V;
    static List<List<Node>> graph;
    static class Node {
        Integer next;
        Integer weight;

        Node(int next, int weight) {
            this.next = next;
            this.weight = weight;
        }
    }

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        V = Integer.parseInt(br.readLine());
        graph = new ArrayList<>();

        for (int i = 0; i <= V; i++) {
            graph.add(new ArrayList<>());
        }

        for (int i = 0; i < V; i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());

            int idx = Integer.parseInt(st.nextToken());

            while (true) {
                int next = Integer.parseInt(st.nextToken());
                if (next == -1) break;
                int weight = Integer.parseInt(st.nextToken());
                graph.get(idx).add(new Node(next, weight));
            }
        }

        int[] dist1 = bfs(1);

        int maxPath = 0;
        int startOfDiameter = 1;
        for (int i = 2; i <= V; i++) {
            if (dist1[i] > maxPath) {
                maxPath = dist1[i];
                startOfDiameter = i;
            }
        }

        int[] dist2 = bfs(startOfDiameter);

        int answer = 0;
        for (int i : dist2) {
            answer = Math.max(answer, i);
        }

        System.out.print(answer);
    }
    static int[] bfs(int idx) {
        int[] dist = new int[V+1];
        Arrays.fill(dist, -1);

        Queue<Integer> queue = new LinkedList<>();
        queue.add(idx);
        dist[idx] = 0;

        while (!queue.isEmpty()) {
            int current = queue.poll();
            for (Node v : graph.get(current)) {
                int nextNode = v.next;
                if (dist[nextNode] == -1) {
                    queue.add(nextNode);
                    dist[nextNode] = dist[current] + v.weight;
                }
            }
        }

        return dist;
    }
}

Copy link
Member

@9kyo-hwang 9kyo-hwang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ˜€ν μ”¨ μ•Œκ³ λ¦¬μ¦˜ μˆ˜μ—… 듀을 λ•Œ, κ·Έλ£Ή μ•‘ν‹°λΉ„ν‹° 문제둜 λ‚΄μ…”μ„œ μ„€λͺ… λ“€μ—ˆλ˜ 기얡이 μžˆλ„€μš”. λ¬Όλ‘  κ·Έλ•ŒλŠ” 이해 λͺ»ν–ˆμ§€λ§Œ...

  1. 아무 λ…Έλ“œ(보톡 루트)λ₯Ό 작고 DFS -> κ°€μž₯ λ¨Ό λ…Έλ“œ νšλ“
  2. κ°€μž₯ λ¨Ό λ…Έλ“œ κΈ°μ€€μœΌλ‘œ λ‹€μ‹œ DFS -> λ‹€μ‹œ κ°€μž₯ λ¨Ό λ…Έλ“œ νšλ“
  3. 두 κ°€μž₯ λ¨Ό λ…Έλ“œ κ°„ 길이가 트리의 지름

μš” μ•„μ΄λ””μ–΄λ§Œ μˆ™μ§€ν•˜κ³  μžˆλ‹€λ©΄ κ΅¬ν˜„μ€ λ‚˜λ¦„ κ°„λ‹¨ν•˜κ²Œ ν•  수 μžˆλŠ” 것 κ°™λ„€μš” :) 1967 트리의 지름 λ˜‘κ°™μ€ λ¬Έμ œλ‹ˆκΉŒ 점수 λ‚ λ¨Ήν•˜μ‹­μ‡Ό ^^7

#include <iostream>
#include <vector>

using namespace std;
using pii = pair<int, int>;

int V;
vector<vector<pii>> tree;
vector<bool> visited;
int max_node = 0, max_dist = 0;

void dfs(int from, int total_dist = 0) {
  visited[from] = true;

  if (total_dist > max_dist) {
    max_node = from;
    max_dist = total_dist;
  }

  for (const auto &[to, distance] : tree[from]) {
    if (!visited[to]) {
      dfs(to, total_dist + distance);
    }
  }
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  
  cin >> V;
  tree.resize(V + 1);

  for (int i = 1; i <= V; ++i) {
    int src_num;
    cin >> src_num;

    int dst_num, dst_dist;
    while (cin >> dst_num && dst_num != -1) {
      cin >> dst_dist;
      tree[src_num].emplace_back(dst_num, dst_dist);
    }
  }

  visited.assign(V + 1, false);
  dfs(1);
  visited.assign(V + 1, false);
  dfs(max_node);

  cout << max_dist;
  
  return 0;
}

Copy link
Collaborator

@kangrae-jo kangrae-jo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

트리의 지름을 κ΅¬ν•˜λŠ” 방법을 μ•Œκ³ μžˆμ–΄λ„ μ–΄λ ΅λ„€μš”.
50λΆ„ 정도 κ±Έλ ΈμŠ΅λ‹ˆλ‹€.

μ²˜μŒμ— μ–΄λ–€ λ…Έλ“œλ‘œ λΆ€ν„° κ°€μž₯ λ¨Ό λ…Έλ“œλ₯Ό μ°Ύκ³ ,
κ·Έ λ…Έλ“œμ—μ„œ κ°€μž₯ λ¨Ό λ…Έλ“œκΉŒμ§€μ˜ κ°€μ€‘μΉ˜κ°€ 트리의 지름이죠.

처음 λ…Έλ“œλ₯Ό μ°Ύμ„λ•Œ, κ·Έ λ…Έλ“œλ₯Ό μ €μž₯ν•˜λŠ” 방식을 μƒκ°ν•΄λ΄€λŠ”λ°,
μ €λŠ” solution ν•¨μˆ˜μ—μ„œ 리턴을 ν•΄λ²„λ¦¬κ²Œ ν•˜κ³  μ‹Άμ–΄μ„œ pair<int,int> 둜 두고 weight와 endnodeλ‘œμ„œ ν™œμš©ν–ˆμŠ΅λ‹ˆλ‹€.

κ·Έ κ³Όμ •μ—μ„œ endnode λ₯Ό = 0 으둜 μ΄ˆκΈ°ν™” ν•΄λ²„λ¦¬λŠ” 잘λͺ»μ„ ν•΄μ„œ ν•œ 10λΆ„ 이상 λ‚ λ¦° 것 κ°™λ„€μš”.
쒋은 문제 κ°μ‚¬ν•©λ‹ˆλ‹€.

그리고 방문처리λ₯Ό forλ¬Έ λ°–μ—μ„œ ν•΄μ•Όν•˜λŠ” μ΄μœ λŠ” μ •ν™•νžˆ λͺ¨λ₯΄κ² μ§€λ§Œ...
μ•„λ§ˆ if(len> max)이 둜직이 forλ¬Έ 밖에 μžˆμ–΄μ„œ 그런거 μ•„λ‹κΉŒμš”.
λ©”μ„œλ“œκ°€ intλ₯Ό λ¦¬ν„΄ν•˜κ²Œ ν•˜λ©΄ λ¬Έμ œκ°€ 없을 것 κ°™μ•„μš” (ν•΄λ³΄μ§€λŠ”μ•ŠμŒ)

#include <iostream>
#include <vector>

using namespace std;

int V;
vector<vector<pair<int, int>>> graph;

pair<int,int> solution(vector<bool>& v, int cur) {
    int answer = 0;
    int node = cur;

    for (auto [next, w] : graph[cur]) {
        if (v[next]) continue;
        v[next] = true;

        auto [candiW, candiN] = solution(v, next);
        if (answer < candiW + w) {
            answer = candiW + w;
            node = candiN;
        }
    }
    return {answer, node};
}

int main() {
    cin >> V;

    graph = vector<vector<pair<int, int>>>(V + 1);
    for (int i = 1; i <= V; i++) {
        int a, b, w;
        cin >> a;

        while (cin >> b && b != -1) {
            cin >> w;
            graph[a].push_back({b, w});
            graph[b].push_back({a, w});
        }
    }

    vector<bool> visited(V + 1, false);
    visited[1] = true;
    auto [weigth, node] = solution(visited, 1);

    visited.assign(V + 1, false);
    visited[node] = true;
    cout << solution(visited, node).first;

    return 0;
}

@g0rnn g0rnn merged commit 57f6169 into main Nov 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants