본문 바로가기

알고리즘 관련/BOJ

BOJ)13016 내 왼손에는 흑염룡이 잠들어 있다

문제: icpc.me/13016


오랜만에 문제 포스팅을 한다.


문제를 요약하면 한 정점 v에서 다른 정점으로의 최단거리를 dist[i] (i: 1~n) 이라고 했을 때, dist[i]의 최댓값을 모든 정점 v에 대해 구하는 문제이다.


물론 한 정점에서 dist[i]의 최댓값을 구하는건 dfs를 수행하여 쉽게 해결할 수 있지만 모든 정점에 대해 구하게 될 경우 정점의 개수가 5만이므로 시간초과를 보게 될 것이다.


하지만 조금 생각해보면 한 정점에서의 부터 다른 정점으로 부터의 최단 거리 중 최댓값은 트리의 지름의 양 끝 단말 노드 중 하나로의 거리라는 것을 알 수 있다.

(만약 트리 지름의 단말 노드가 아닌 다른 리프로 부터의 거리가 최댓값이라면, 트리의 지름보다 긴 거리가 생긴다는 뜻이므로 모순이된다.)


따라서 트리의 지름의 단말 노드 u,v를 구해준 뒤 u,v로의 거리만 dfs 2번을 수행하여 구해준 뒤 비교하여 출력해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
vector<vector<pair<int,int>>> vt;
vector<int> dist;
int n,x,y,z,maxlen,v,u,res[50050];
const int inf=2e9+10;
void dfs(int here,int dis){
    dist[here]=dis;
    if(dist[here]>maxlen){
        maxlen=dist[here];
        u=here;
    }
    for(auto next:vt[here]){
        if(dist[next.first]!=inf)continue;
        dfs(next.first,dis+next.second);
    }
}
int main(){
    scanf("%d",&n);
    vt.resize(n+1);
    for(int i=0;i<n-1;i++){
        scanf("%d%d%d",&x,&y,&z);
        vt[x].push_back({y,z});
        vt[y].push_back({x,z});
    }
    dist.assign(n+1,inf);
    dfs(1,0);
    v=u,maxlen=0;
    dist.assign(n+1,inf);
    dfs(v,0);
    for(int i=1;i<=n;i++)
        res[i]=dist[i];
    dist.assign(n+1,inf);
    dfs(u,0);
    for(int i=1;i<=n;i++)
        printf("%d\n",max(res[i],dist[i]));
    return 0;
}
cs


'알고리즘 관련 > BOJ' 카테고리의 다른 글

BOJ)1222 홍준 프로그래밍 대회  (0) 2018.06.25
BOJ)15675 괴도 강산  (0) 2018.06.24
BOJ)15673 헤븐스 키친2  (1) 2018.05.06
BOJ)2171 직사각형의 개수  (0) 2017.12.19
BOJ)14943 벼룩 시장  (0) 2017.12.18