코딩/백준

[백준] 1967번 트리의 지름 - C++

최선을 다하는 2022. 10. 5. 14:38

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

 

1967번: 트리의 지름

파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n-1개의 줄에 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 연

www.acmicpc.net

문제

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

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

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

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

입력

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

출력

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


     트리의 지름은 아무 점에서 제일 먼 점을 찾고 해당 점에서 가장 먼 점을 찾게 된다면 트리의 지름이 된다. 무방향 그래프이기 때문에 vis를 활용하여 루프에 빠지지 않게 한다. 결국 가장 먼 점을 구하는 알고리즘은 같기 때문에 처음 1번 노드로 시작하는 함수는 가장 먼 노드를 반환하고 해당 노드로 시작하는 함수는 거리를 반환하면 같은 함수를 활용할 수 있다.

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

vector <pair<int,int>> adj[10001];
int a,b,c,n;
int dis[10001] = {0};
bool vis[10001] = {0};

int dijk(int k){
    int maxdis = 0, maxidx = 0;
    dis[k] = 0;
    queue <int> q;
    q.push(k);
    while(!q.empty()){
        int cur = q.front();
        q.pop();
        vis[cur] = true;
        for(auto i : adj[cur]){
            if(!vis[i.first]){
                dis[i.first] = i.second + dis[cur];
                if(dis[i.first] > maxdis){
                    maxdis = dis[i.first];
                    maxidx = i.first;
                }
                q.push(i.first);
            }
        }
    }
    if(k == 1)
        return maxidx;
    else
        return maxdis;
}

int main (){
    int temp;

    cin >> n;
    for(int i = 0; i < n - 1; i++){
        cin >> a >> b >> c;
        adj[a].push_back(make_pair(b,c));
        adj[b].push_back(make_pair(a,c));
    }
    temp = dijk(1);
    memset(dis,0,sizeof(dis));
    memset(vis,0,sizeof(vis));
    cout << dijk(temp);
}

    이전에 트리의 지름 문제를 풀었는데 안 풀려있길래 다시 풀어보았다. 알고 보니 번호가 다른 유사한 문제였다! 그래도 트리의 지름이라는 개념이 인상적이었는지 구하는 방법을 잊지 않고 있었다. 처음에는 어제 사용했던 다익스트라를 사용하려다가 생각해보니 최댓값을 구하는 것이라 결국 끝까지 가보아야 한다는 생각에 일반 queue를 사용하였다. 처음에 한번 돌리고 구한 노드에서 진행을 못하길래 다시 살펴보니 단방향으로만 입력을 받아서 9번 노드는 자식이 없어서 진행을 못하는 것이었다! 그래서 무방향 그래프로 바꾸고 vis를 활용하니 문제를 풀 수 있었다. 풀어본 문제였지만 그래도 오랜만에 한 번에 정답을 받을 수 있어서 기뻤다. 코딩을 놓으니깐 다시 감 잡기가 이렇게 어렵다. 앞으로 취준 하기 전까지는 진짜 게을리하면 안 되겠다!

'코딩 > 백준' 카테고리의 다른 글

[백준]1504번 특정최단경로 - C++  (0) 2022.11.02
[백준]13549번 숨바꼭질3 - C++  (0) 2022.11.01
[백준] 1753번 최단경로 - C++  (0) 2022.10.04
[백준]7576번 토마토 - C/C++  (0) 2022.10.02
[백준] 2580번 스도쿠 -C/C++  (1) 2022.09.30