https://www.acmicpc.net/problem/1167

 

1167번: 트리의 지름

트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지

www.acmicpc.net


    •  1967번 트리의 지름 문제와 매우 유사한 문제이다.
    • 똑같이 dfs 를 두번 돌려서, 양 극점을 찾아가면서 푸는 접근 방식은 동일하다.
    • 그러나 노드들이 양방향으로 연결될 수 있고, 그래프 안에서 순환이 발생할 수 있기 때문에 방문 여부에 대한 배열을 두고 재방문하지 않으면서 탐색해야 한다.
    • 이 문제 같은 경우는, 트리라기보다는 그래프의 지름을 찾는다고 표현하는게 맞을 것 같다.

#include <iostream>
#include <vector>

using namespace std;

int V, v, u, w;
int node, answer;
vector<vector<pair<int,int>>> tree;
vector<bool> visited;

void dfs(int s, int dist)
{
    if(dist > answer)                           // dfs 안에서 최대거리와 해당 노드 갱신
    {
        answer = dist;
        node = s;
    }
    for(int i = 0 ; i < tree[s].size() ; i++)  // 재귀 호출
    {
        pair<int, int> cur = tree[s][i];
        if(visited[cur.first]) continue;        // 방문했던 노드는 재방문하지 않음
        visited[cur.first] = true;
        dfs(cur.first, dist + cur.second);
    }
}

int main(void)
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> V;
    for(int i = 0 ; i <= V ; i++)
    {
        vector<pair<int,int>> node;
        tree.push_back(node);
        visited.push_back(false);
    }
    for(int i = 1 ; i <= V ; i++)
    {
        cin >> v >> u;
        while(u != -1)
        {
            cin >> w;
            tree[v].push_back({u, w});
            cin >> u;
        }
    }

    visited[1] = true;                          // 임의의 점에서 출발하여 최대거리인 노드 확인
    dfs(1, 0);
    for(int i = 1 ; i <= V ; i++) visited[i] = false;
    visited[node] = true;                       // 해당 노드부터 다시 최대거리를 확인하면 트리의 지름이 됨
    dfs(node, 0);
    cout << answer << endl;
}

'PS > BOJ' 카테고리의 다른 글

[백준] 11055 : 가장 큰 증가 부분 수열  (0) 2021.05.17
[백준] 1238 : 파티  (0) 2021.05.16
[백준] 1449 : 수리공 항승  (0) 2021.05.14
[백준] 1717 : 집합의 표현  (0) 2021.05.12
[백준] 12852 : 1로 만들기 2  (0) 2021.05.11

+ Recent posts