Open yeongleej opened 4 days ago
79,999(노드 + 간선) * 10,000(노드쌍)
이므로 시간초과10,000 * 40,000
(최악의 경우는 4억번 연산을 하는 것이지만, 시간 내에 연산하는 것 같음)Node(int e, int w)
, ArrayList<Node> adj[]
사용BFS
시작하고, dis
, depth
, p
값 채우기
int[] dis
: 루트로부터 자기 자신까지의 거리int[] depth
: 트리에서 자신의 depth 구하기int[] p
: 자기 자신의 직접적인 부모가 누구인지 저장 long LCA(int a, int b)
a
, b
의 최소공통조상 구하고, 두 점 간 사이 거리 구하기
(루트 ~ a 까지의 거리) + (루트 ~ b 까지의 거리) - 2 * (루트 ~ 최소공통조상까지의 거리)
a
와 b
의 depth
가 다르다면 depth
를 작은걸로 맞춰줘야 됨
depth
는 항상 a
의 depth
가 작다고 설정함depth
맞추고 한 칸씩 단계별로 자기 자신을 부모로 값을 바꾸면서, a == b
가 될 때까지 반복한 번 풀어봤던 문제여서 문제 접근 방법을 알고 있었습니다!
LCA(최소공통조상)
이용
DFS이용
(기본)
O(NM)
2^i승에대한 dp이용
O(MlogN)
setTree()
)
parents[nxt.u][0] = x;
설정setParents()
)
parents[j][i] = parents[parents[j][i - 1]][i - 1];
LCA()
)
for (int i = mxDepth - 1; i >= 0; i--) { // 부모가 다르면 같이 부모찾으러 떠나기
if (parents[a][i] != parents[b][i]) {
a = parents[a][i];
b = parents[b][i];
}
}
return parents[a][0]; // 최종적으로 찾은 부모 값 반환
LCA... 처음 알게된 개념인데 쉽지 않네요.... 개념 공부하면서 했는데도.. 저 근데 궁금한게 parents에서 최대 부모값 배열 크기를 설정할때, 트리의 최대높이(logN+1)로 설정하는데 편향된 트리일 경우 크기가 더 커야할텐데 왜 그냥 logN+1로 사용하는건지 아시나요....??
수빈님 질문에 대해 답변 드리겠습니다! (어디에 답변해야될지 모르겠어서,,, 여기에 올려욤,,)
우선 LCA를 구하는 방법이 크게 두 가지가 있는데, 첫 번째가 일반적인 방법으로 제가 사용한 방법이고, 수빈님이 하신건 질의의 개수가 많을 때 사용하는 개선된 LCA입니다.
개선된 LCA에서 parents 배열의 크기를 (logN + 1)
로 설정해야 되는 이유는 이게 단순히 트리의 최대 깊이를 의미하는 것이 아니라, 어떤 지점에 대해 2^k
까지의 부모 노드가 뭔지 저장해야 되기 때문에 그런 것으로 알고 있습니다. 그래서 편향트리가 되더라도 상관없게 되는 것 같습니다!
예시를 2개 그려봤는데요,, 혹시 잘못된거 같은 내용 있음 말해주세요!!
log2^N
> log2^40000
은 15.3)dfs
메소드
dp
메소드
//전체 트리에서 각 노드별로 다중 차수 부모 노드들 저장
static void saveParents(){
for(int from=1; from<MAX; from++){
for(int to=1; to<n+1; to++){
int parent = dp[to][from-1]; //특정노드의 레벨의 부모노드
dp[to][from] = dp[parent][from-1];
}
}
}
lca
메소드
출발노드-도착노드
가 있을 때 둘 중 하나를 더 깊은 노드
로 기준점 잡기
출발노드-도착노드
가 서로 다른 레벨에 있을 경우 깊이를 맞추기
깊은 노드
를 현재 레벨로 올리면서 갱신출발노드-도착노드
의 깊이 레벨을 맞추고, 서로 같은 부모를 가지고 있다면 공통 부모노드 반환정말... 너무..어렵네요... 설명은 이해가 가는데 dp 배열에 메모리제이션 구현 코드 부분이 너무 이해하기 어려웠어요...
=> 다익스트라 이용 : N O(N logN) -> 시간초과 => 최소 공통 조상(LCA) : O(N M) -> 가능
lca(a, b)