Notice
Recent Posts
Recent Comments
Link
HwangHub
[유니온파인드/Java] SWEA 1248 공통조상 본문
문제 해석
트리 구조에서 공통된 조상 중 가장 가까운 조상을 찾는 건 그래프 알고리즘 중 유니온파인드 알고리즘의 '파인드' 부분을 활용하면 될 것으로 보았다.
아울러 그 노드 기준으로 자식 노드의 개수를 세는 건 dfs로 간단하게 구현할 수 있다.
문제 풀이
시간복잡도 : DFS를 인접리스트로 구현하였고(O(V+E)), 파인드 로직에서 최소 공통 root 노드를 찾기 위한 로직에서 트리 높이(h)가 최악의 경우 노드 개수(V)에 근사해지므로 O(V + E)
이다.
package ssafy.사전학습;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class 공통조상 {
public static int[] parent;
public static int n, m;
public static List<Integer> aList;
public static List<Integer> bList;
public static int cardinality;
public static boolean[] visited;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int t = Integer.parseInt(st.nextToken());
for (int i = 1; i <= t; i++) {
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken()); // 정점 개수
m = Integer.parseInt(st.nextToken()); // 간선 개수
int targetA = Integer.parseInt(st.nextToken()); // target A
int targetB = Integer.parseInt(st.nextToken()); // target B
cardinality = 0;
parent = new int[n + 1];
visited = new boolean[n + 1];
for (int j = 0; j < n+1; j++) {
parent[j] = j;
}
// init parent array
st = new StringTokenizer(br.readLine());
for (int j = 0; j < m; j++) {
int parentNode = Integer.parseInt(st.nextToken());
int childNode = Integer.parseInt(st.nextToken());
parent[childNode] = parentNode;
}
aList = new ArrayList<>();
bList = new ArrayList<>();
// commonRoot (fin)
findRoot(targetA, aList);
findRoot(targetB, bList);
int aListSize = aList.size();
int bListSize = bList.size();
int root = -1;
boolean isEnd = false;
if (aListSize > bListSize) {
for (int j = 0; j < aListSize; j++) {
Integer aElem = aList.get(j);
for (int k = 0; k < bListSize; k++) {
if (aElem.equals(bList.get(k))) {
root = aElem;
isEnd = true;
break;
}
}
if (isEnd) {
break;
}
}
} else {
for (int j = 0; j < bListSize; j++) {
Integer bElem = bList.get(j);
for (int k = 0; k < aListSize; k++) {
if (bElem.equals(aList.get(k))) {
root = bElem;
isEnd = true;
break;
}
}
if (isEnd) {
break;
}
}
}
// cardinality (fin)
visited[root] = true;
cardinality++;
dfs(root);
System.out.println("#" + i + " " + root + " " + cardinality);
}
}
public static int findRoot(int target, List<Integer> li) {
if (target == parent[target]) {
return target;
}
li.add(parent[target]);
return findRoot(parent[target], li);
}
/*
* root 노드를 중심으로
* 인접 리스트 관계를 parent에 담고 있으니,
* parent를 활용하여 그래프 cardinality 탐색하면 되지 않을까?
* DFS를 활용하자.
* */
public static void dfs(int v) {
for (int i = 0; i < n + 1; i++) {
if (!visited[i] && parent[i] == v) {
cardinality++;
visited[i] = true;
dfs(i);
}
}
}
}
'workspace > 알고리즘' 카테고리의 다른 글
[자바/누적합] 코드트리. 연속한 K개의 숫자 (0) | 2024.01.22 |
---|---|
[자바/이진탐색] BOJ 16401. 과자 나눠주기 (0) | 2024.01.21 |
[다익스트라/자바] SWEA 4193. 수영대회 결승전 (1) | 2024.01.06 |
[BFS&DFS/Java] SWEA 7465. 창용 마을 무리의 개수 (2) | 2024.01.05 |
[다익스트라/Java] SWEA 1249. 보급로 (2) | 2024.01.05 |
Comments