ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [BOJ 20894] Brobygge
    문제 풀이/Baekjoon Online Judge 2023. 1. 28. 03:24

    체감 난이도: Platinum IV + 0.2

     

    태그

    더보기
    • Sparse Table (희소 배열)
    • Lowest Common Ancestor (최소 공통 조상)

     

    풀이

    1. \( E = 0 \)이면?

    더보기

    잘 알려진 문제입니다.

     

    \( d[v] = \) \( 1 \)번 정점부터 \( v \)번 정점까지의 길이, \( l = \text{lca}(v, w) \)라고 할 때

    \( \text{dis}(v, w) = \text{dis}(v, l) + \text{dis}(l, w) = d[v]-d[l] + d[w]-d[l] \)입니다.

     

    그러니, \( d[v] \)를 전처리한 후 LCA를 빠르게 구하기 위한 희소 배열까지 만들어주면 됩니다.

     

    2. 추가된 간선을 반드시 타야 한다면?

    더보기

    추가된 간선이 \( v_1 \)번 정점과 \( w_1 \)번 정점을 잇는 길이 \( x_1 \)의 간선이라고 합시다.

    그럼, \( s \)에서 시작해서 \( t \)로 가는 경로는 \( s \Rightarrow v_1 \rightarrow w_1 \Rightarrow t \)로 표현할 수 있습니다.

    이 때의 최단 경로는 \( \text{dis}(s, v_1) + x_1 + \text{dis}(w_1, t) \)가 됩니다.

     

    사실 정확히는 \( s \Rightarrow w_1 \rightarrow v_1 \Rightarrow t \)도 고려해줘야 합니다. 결과는 (같지는 않지만) 비슷하게 나오니 패스하겠습니다.

     

    간선이 2개여도, \( s \Rightarrow v_1 \rightarrow w_1 \Rightarrow v_2 \rightarrow w_2 \Rightarrow t \)를 사용하면 됩니다.

    이 때의 최단 경로는 \( \text{dis}(s, v_1) + x_1 + \text{dis}(w_1, v_2) + x_2 + \text{dis}(w_2, t) \)가 됩니다.

     

    위와 비슷하게, 간선 2개를 타는 경우를 다 따지려면 총 8가지 경우가 있습니다. 코드에서 구경해볼 수 있습니다.

     

    실제로는 반드시 타야 할 필요는 없으므로,

    반드시 탈 때와 그렇지 않을 때 중 더 작은 값을 골라주면 됩니다.

     

    코드

    더보기

    구현의 편의성을 위해, \( E = 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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    vector<pi2> adj[100020];
     
    const int B = 17;
    int spr[20][100020];
    int dep[100020]; ll dis[100020];
     
    void dfs(int now, int pre){
        for (pi2 p : adj[now]){
            int nxt = p.fr, dst = p.sc;
            if (nxt == pre){ continue; }
            spr[0][nxt] = now; dep[nxt] = dep[now]+1; dis[nxt] = dis[now]+dst;
            dfs(nxt, now);
        }
    }
     
    int lca(int v, int w){
        if (dep[v] > dep[w]){ swap(v, w); }
        int dif = dep[w]-dep[v];
        for (int b = B; b >= 0; b--){
            if (dif>>& 1){ w = spr[b][w]; }
        }
        if (v==w){ return v; }
        for (int b = B; b >= 0; b--){
            if (spr[b][v] != spr[b][w]){ v = spr[b][v]; w = spr[b][w]; }
        }
        return spr[0][v];
    }
    inline ll f(int v, int w){
        int l = lca(v, w); return dis[v]-dis[l] + dis[w]-dis[l];
    }
     
    pi3 edg[3];
     
    void Main(){
        int n; cin >> n;
        for (int i = 1; i < n; i++){
            int v, w, x; cin >> v >> w >> x; v++; w++;
            adj[v].push_back({w, x}); adj[w].push_back({v, x});
        }
        dep[1= dis[1= 0; spr[0][1= 1; dfs(11);
        for (int b = 1; b <= B; b++){
            for (int v = 1; v <= n; v++){
                spr[b][v] = spr[b-1][ spr[b-1][v] ];
            }
        }
        int e; cin >> e;
        int v1 = 1, w1 = 1; ll x1 = 1e15;
        int v2 = 1, w2 = 1; ll x2 = 1e15;
        if (1 <= e){ cin >> v1 >> w1 >> x1; v1++; w1++; }
        if (2 <= e){ cin >> v2 >> w2 >> x2; v2++; w2++; }
        int q; cin >> q; while (q--){
            int v, w; cin >> v >> w; v++; w++;
            cout << min({
                f(v,w),
                f(v,v1)+x1+f(w1,w),
                f(v,w1)+x1+f(v1,w),
                f(v,v2)+x2+f(w2,w),
                f(v,w2)+x2+f(v2,w),
                f(v,v1)+x1+f(w1,v2)+x2+f(w2,w),
                f(v,v1)+x1+f(w1,w2)+x2+f(v2,w),
                f(v,w1)+x1+f(v1,v2)+x2+f(w2,w),
                f(v,w1)+x1+f(v1,w2)+x2+f(v2,w),
                f(v,v2)+x2+f(w2,v1)+x1+f(w1,w),
                f(v,v2)+x2+f(w2,w1)+x1+f(v1,w),
                f(v,w2)+x2+f(v2,v1)+x1+f(w1,w),
                f(v,w2)+x2+f(v2,w1)+x1+f(v1,w),
            }) << endl;
        }
    }
    cs
Designed by Tistory.