페이지

3176번: 도로 네트워크

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


#include<stdio.h>
#include<vector>
#include<algorithm>
using namespace std;
const int MAX_N = 100000, LGN = 16;
int n, k;
int dp[MAX_N + 1][LGN + 1], lv[MAX_N + 1];
bool ck[MAX_N + 1];
vector<pair<intint> > adj[MAX_N + 1];
struct st {
    int mini, maxi;
    st() {}
    st(int _mini, int _maxi) :mini(_mini), maxi(_maxi) {}
    st operator+(st i) const {
        return st(min(mini, i.mini), max(maxi, i.maxi));
    }
}s[MAX_N + 1][LGN + 1];
void dfs(int h) {
    ck[h] = true;
    for (auto t : adj[h]) {
        if (ck[t.first]) continue;
        lv[t.first] = lv[h] + 1;
        dp[t.first][0] = h;
        s[t.first][0] = st(t.second, t.second);
        for (int i = 1; i <= LGN; i++) {
            s[t.first][i] = s[t.first][i - 1] + s[dp[t.first][i - 1]][i - 1];
            dp[t.first][i] = dp[dp[t.first][i - 1]][i - 1];
        }
        dfs(t.first);
    }
}
st res;
void lca(int x, int y) {
    res = st(1e6, 0);
    if (lv[x] < lv[y]) swap(x, y);
    for (int i = LGN; i >= 0; i--)
        if (1 << i <= lv[x] - lv[y])
            res = res + s[x][i], x = dp[x][i];
    if (x == y) return;
    for (int i = LGN; i >= 0; i--) {
        if (dp[x][i] != dp[y][i]) {
            res = res + s[x][i] + s[y][i];
            x = dp[x][i];
            y = dp[y][i];
        }
    }
    res = res + s[x][0] + s[y][0];
}
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i++) {
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        adj[a].push_back({ b, c });
        adj[b].push_back({ a, c });
    }
    dfs(1);
    scanf("%d", &k);
    for (int i = 0; i < k; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        lca(a, b);
        printf("%d %d\n", res.mini, res.maxi);
    }
    return 0;
}

댓글 6개 :

  1. for (int i = 1; i <= LGN; i++){
    s[t.first][i] = s[t.first][i - 1] + s[dp[t.first][i - 1]][i - 1];
    dp[t.first][i] = dp[dp[t.first][i - 1]][i - 1];
    }
    25~27번째줄인데 이거 뭐하는건지 설명 좀 부탁드려도될까요?..

    답글삭제
  2. lca를 구하기 위해 sparse table을 만드는 과정입니다.

    t.first - 인덱스, 노드 번호
    dp[x][i] - x의 2^i 번째 위에 있는 조상 번호
    s[x][i] - x와 x의 2^i 번째 위에 있는 조상 사이 간선들의 최소, 최대 가중치를 가지는 구조체

    이후에 두 노드 사이의 lca 및 최소, 최대 가중치를 빠르게 구하기위해 s[i][j]와 dp[i][j]를 모두 구해야 합니다.
    t.first=x라 한다면
    dp[x][i]는 x의 2^i 위의 조상을 의미하고, 이는 (x의 2^i-1 위의 조상)의 2^i-1 위의 조상 즉, dp[dp[x][i-1]][i-1]로 구할 수 있습니다.
    비슷한 원리로
    s[x][i]=s[x][i-1]+s[dp[x][i-1]][i-1] 는
    (x~2^i위의 조상 최소,최대) = (x~2^i-1위의 조상 최소,최대)과 (2^i-1위의 조상~2^i위의 조상 최소,최대)사이 최소,최대 연산을 의미합니다.
    ('+'는 구조체의 작동자를 보면 알 수 있듯이 일반적으로 알려진 덧셈이 아닌 구조체간 최소, 최대를 구하는 연산으로 정의되어 있습니다.)

    아래 사이트를 참고하시길 바랍니다.

    sparse table 관련:
    http://cloge.tistory.com/24
    lca 관련:
    https://www.topcoder.com/community/data-science/data-science-tutorials/range-minimum-query-and-lowest-common-ancestor/#Another%20easy%20solution%20in%20O(N%20logN,%20O(logN)

    답글삭제
  3. 빠른답변감사합니다 ㅎㅎ..
    다 읽어보고 오겠습니다.
    정말감사합니다

    답글삭제
  4. 풀었습니다 ! 감사합니다
    물론 거의 코드를 배꼇지만..; ㅎㅎ;

    답글삭제
  5. s[x][i]=s[x][i-1]+s[dp[x][i-1]][i-1] 는
    (x~2^i위의 조상 최소,최대) = (x~2^i-1위의 조상 최소,최대)과 (2^i-1위의 조상~2^i위의 조상 최소,최대)사이 최소,최대 연산을 의미합니다.
    ('+'는 구조체의 작동자를 보면 알 수 있듯이 일반적으로 알려진 덧셈이 아닌 구조체간 최소, 최대를 구하는 연산으로 정의되어 있습니다.)
    ==>이부분을 java로 바꾸려면 어떻게 해야 하나요?

    답글삭제
  6. JAVA는 익숙지 않아서 모르겠습니다;;

    답글삭제