출처: https://3months.tistory.com/307 [Deep Play]

백준/Tree

[BOJ] 1167 트리의 지름 C++

코딩하는 랄뚜기 2021. 8. 9. 13:35

 

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

 

1167번: 트리의 지름

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

www.acmicpc.net

이 문제를 대충 요약하자면 트리에서 정점->정점까지 가장 긴 거리를 구하는 것이다. 

내가 이 문제를 보고 무조건 시작 또는 끝에는 트리의 리프노드일 것을 알았다. 그래서 모든 리프노드(연결 된 노드가 하나밖에 없는 노드)를 구해서 dfs를 각각 돌려 그 중 최댓값을 구하면 되겠다고 생각했는데 바로 시간초과가 떴다.

고민을 하다가 다른 분의 코딩을 참조 했는데 알고리즘은 다음과 같다.

1. 임의의 점을 루트노드로 잡고 거리가 최대인 리프노드를 구한다.

2. 리프노드를 로트노드로 잡고 최대 거리를 구하면 이것이 트리의 지름이다.

처음 이걸 보고 한참 생각했다. 친구가 설명을 해줬는데도 바로 와닿지 않아서 밑에 블로그를 보고 한참 생각하다 깨달았다.

https://blog.myungwoo.kr/112

 

트리의 지름 구하기

트리에서 지름이란, 가장 먼 두 정점 사이의 거리 혹은 가장 먼 두 정점을 연결하는 경로를 의미한다. 선형 시간안에 트리에서 지름을 구하는 방법은 다음과 같다: 1. 트리에서 임의의 정점 $x$를

blog.myungwoo.kr

(블로그를 참조 할때 d(t,y)=max(d(t,u),d(t,v))부분을 d(t,y)>=max(d(t,u),d(t,v))로 바꿔줘야한다.)

트리에서 정점 u와 정점 v를 연결하는 경로가 트리의 지름이라고 가정하고 임의의 정점 x를 정하고, 정점 x에서 가장 먼 정점 y를 찾았을 때, u,v,x,y가 모두 다른 경우의 수는 존재하지 않는다.(반드시 y가 u,v이거나 x가 u,v여야 한다.)

 

코드

#include <iostream>
#include <vector>
using namespace std;

bool check[100001];
vector<pair<int,int> > v[100001];
vector<int> end_node;
int max_idx,max_dist=0;
int N;
void dfs(int start,int dist_sum){
    check[start]=true;
    bool flag=false;
    int size=v[start].size();
    for(int i=0;i<size;i++){
        int go=v[start][i].first;
        int dist=v[start][i].second;
        if(!check[go]){
            dfs(go,dist_sum+dist);
            flag=true;
        }
    }
    check[start]=false;
    if(flag) return;
    if(max_dist<dist_sum){
        max_idx=start;
        max_dist=dist_sum;
    }
}
int main(){
    int start;
    cin>>N;
    for(int i=1;i<=N;i++){
        int from;
        cin>>from;
        while(1){
            int to,dist;
            cin>>to;
            if(to==-1) break;
            cin>>dist;
            v[from].push_back(make_pair(to,dist));
        }
        if(v[from].size()==1) start=from;
    }
    int ans=0;
    dfs(1,0);//임의의 점
    dfs(max_idx,0); //최대값을 갖는 인덱스에서 dfs
    cout<<max_dist;
    return 0;
}

 

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

[BOJ] 4256 트리 C++  (0) 2021.08.11
[BOJ] 19581 두 번째 트리의 지름 C++  (0) 2021.08.09
[BOJ] 1655 가운데를 말해요 C++  (0) 2021.08.05
[BOJ] 1918 후위표기식 C++  (0) 2021.08.04
[BOJ] 1935 후위표기식2 C++  (0) 2021.08.04