#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<int, int> > 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; }
3176번: 도로 네트워크
https://www.acmicpc.net/problem/3176
피드 구독하기:
댓글
(
Atom
)
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번째줄인데 이거 뭐하는건지 설명 좀 부탁드려도될까요?..
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)
빠른답변감사합니다 ㅎㅎ..
답글삭제다 읽어보고 오겠습니다.
정말감사합니다
풀었습니다 ! 감사합니다
답글삭제물론 거의 코드를 배꼇지만..; ㅎㅎ;
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로 바꾸려면 어떻게 해야 하나요?
JAVA는 익숙지 않아서 모르겠습니다;;
답글삭제