Open WonYong-Jang opened 6 years ago
추천 문제
11438번: LCA 2
1761번: 정점들의 거리
8012번: Byteasar the Travelling Salesman
15480번: LCA와 쿼리 (★)
1396번: 크루스칼의 공 (★)
public class Main {
static int N, K, max_level;
static final int max_node = 100005;
static int[][] maxDp = new int[max_node][20];
static int[][] minDp = new int[max_node][20];
static int[][] parent = new int[max_node][20];
static int[] depth = new int[max_node];
static ArrayList<ArrayList<Node>> adj = new ArrayList<ArrayList<Node>>();
public static void main(String[] args) throws IOException {
depth[0] = -1;
dfs(1,0,0);
make_dp();
st = new StringTokenizer(br.readLine());
K = Integer.parseInt(st.nextToken());
for(int i=1; i<= K; i++)
{
st = new StringTokenizer(br.readLine());
dx = Integer.parseInt(st.nextToken());
dy = Integer.parseInt(st.nextToken());
int tx = dx, ty = dy;
int ansMax = -1, ansMin = Integer.MAX_VALUE;
if(depth[dx] != depth[dy] )
{
if(depth[dx] > depth[dy]) {
int tmp = dx;
dx = dy;
dy = tmp;
}
for(int k = max_level; k >= 0; k--)
{
if(depth[dx] <= depth[parent[dy][k]])
{
// 주의 dy 갱신하기 전에 먼저 (위치 주위!!)
// dx 는 고정이기 때문에 dy 만 해주는 것 주의!!! // dx 도 같이 비교했다가 답 틀림
ansMin = min(ansMin, minDp[dy][k]);
ansMax = max(ansMax, maxDp[dy][k]);
dy = parent[dy][k];
}
}
}
int lca = dx;
if(dx != dy)
{
for(int k = max_level; k >= 0; k--)
{
if(parent[dx][k] != parent[dy][k])
{
ansMax = max(ansMax, max(maxDp[dx][k], maxDp[dy][k]));
ansMin = min(ansMin, min(minDp[dx][k], minDp[dy][k]));
dx = parent[dx][k];
dy = parent[dy][k];
}
lca = parent[dx][k];
}
}
if(dx != lca)
{
ansMin = min(ansMin, min(minDp[dx][0], minDp[dy][0]));
ansMax = max(ansMax, max(maxDp[dx][0], maxDp[dy][0]));
}
bw.write(ansMin+" "+ansMax+"\n");
}
bw.flush();
}
public static void dfs(int cur, int p, int cost)
{
depth[cur] = depth[p] + 1;
parent[cur][0] = p;
maxDp[cur][0] = cost;
minDp[cur][0] = cost;
for(int i =1; i<= max_level; i++)
{
int temp = parent[cur][i-1];
parent[cur][i] = parent[temp][i-1];
}
for(Node next : adj.get(cur))
{
if(next.dx != p)
{
dfs(next.dx, cur, next.cost);
}
}
}
public static void make_dp()
{
for(int jump = 1; jump <= max_level; jump++)
{
for(int cur =1; cur <= N; cur++)
{
int tmp = parent[cur][jump-1];
maxDp[cur][jump] = max(maxDp[cur][jump-1], maxDp[tmp][jump-1]);
minDp[cur][jump] = min(minDp[cur][jump-1], minDp[tmp][jump-1]);
}
}
}
}
(r, u) / (r, v) / (u, v) 의 lca들의 depth들 중 가장 큰 값!!
leftDepth = depth[dx];
rightDepth = depth[dy];
lcaDepth = depth[lca];
leftHeight = leftDepth - lcaDepth + 1;
rightHeight = rightDepth - lcaDepth + 1;
int ans = 0, target =0, sum = 1;
if(leftHeight >= k) { // 왼쪽에서 k 번째 찾아
target = dx;
}
else if(leftHeight < k) {
temp = k - leftHeight;
k = rightHeight - temp;
target = dy;
}
Lowest Common Ancestor
가장 가까운 위치의 공통 조상을 찾는데 쓰이거나 두 노드의 가장 가까운 거리를 찾는데 사용
LCA
시나리오
1) 두 노드가 주어지게 되면 두 노드의 깊이를 구함 ( depth 배열 이용 ) 2) 두 노드들 중 더 깊은 곳에 있는 노드를 더 얖은 곳에 있는 노드 위치까지 끌어 올려줌 2-1) 부모노드로 계속 한칸씩 끌어올리면서 깊이를 확인 / 두 노드가 같은 깊이 상태까지 3) 두 노드 깊이가 같으나 두 노드의 값이 같지 않다면 두 노드 모두 부모노드로 끌어올리면서 같은지 확인 3-1) 두 노드가 같아질때가 최소 공통 조상
LCA2
DP를 이용하여 해결
시나리오
1) 깊이가 더 깊은 노드를 깊이가 더 낮은 노드까지 노드를 올려준다
LCA2 를 이용한 정점들간의 거리
출처 링크 : https://www.crocus.co.kr/660