1. ๋ฌธ์ ์ ๋ํ์ฌ ๐ฆ
- ๋ฌธ์ ๋งํฌ: https://www.acmicpc.net/problem/22860
(1) ์กฐ๊ฑด ๋ถ์ ๐
๋ฌธ์ ์์ ์๊ตฌํ๋ ํด๋์ ํ์ ํ์ผ ์ข ๋ฅ์ ๊ฐ์๋ฅผ ์ถ๋ ฅํ๋ผ.
- main ํด๋ ์๋ ๊ฐ์ ์ด๋ฆ์ ํด๋๋ 2๊ฐ ์ด์ ์กด์ฌํ ์ ์๋ค.
- ํ ํด๋๋ ์์ ์ ๋ ๋ฒจ์์ ๊ฐ์ ์ด๋ฆ์ ํ์ผ์ ๋ ๊ฐ ์ด์ ๊ฐ์ง์ง ๋ชปํ๋ค.
```bash
-- ๋ถ๊ฐ๋ฅ ์์
FolderA
ใดfile1
ใดfile1
# 2. ์ฝ๋๊ฐ ๋์ค๊ธฐ๊น์ง ๐ ๏ธ
**`KEY WORD`: `์๋ฃ๊ตฌ์กฐ`, `์ ๋์จํ์ธ๋`**
## (0) ์๋ฃ ๊ตฌ์กฐ ์ธํ
ํด๋น ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก HashMap 3๊ฐ์ ์ ๋์จ ํ์ธ๋์ฉ `parents` ๋ฐฐ์ด์ด ํ์ํ๋ค.
1. ํด๋ ์ด๋ฆ๋ง ์ฃผ์ด์ง๋ค. ํด๋ ์ด๋ฆ์ผ๋ก๋ index ํ์ฉ ํ์ด๊ฐ ์ด๋ ต๋ค.
- ๊ณ์ธต ๊ตฌ์กฐ ํํ ๋ฐ ์ ๋์จ ํ์ธ๋ ๊ตฌํ์ ์ํด์๋ ๋
ธ๋๋ง๋ค ๋ฒํธ๋ฅผ ๋ถ์ด๋ ๊ฒ์ด ์์ํ๋ค. ๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ด HashMap์ ์ด์ฉํด ๋ฒํธ๋ฅผ ๋ถ์ธ๋ค.
- key = ํด๋ ์ด๋ฆ, value = ํด๋ ๋ฒํธ
- key = ํ์ผ ์ด๋ฆ, value = ํ์ผ ๋ฒํธ
- key = ํด๋ ์ด๋ฆ, value = HashSet(ํ์ ๋๋ ํ ๋ฆฌ ํฌํจ ์์ ์ด ๋ณด์ ํ ํ์ผ์ ๋ฒํธ๋ค)
2. ์ ๋์จ ํ์ธ๋์ ์์ ์ด ๋ณด์ ํ ๋์ ํ์ผ ๊ฐ์๋ฅผ ์ํ ๋ฐฐ์ด๋ ๋ ๊ฐ ๋ง๋ ๋ค.
## (1) ์
๋ ฅ ์ฒ๋ฆฌํ๊ธฐ - ์ ๋์จ ํ์ธ๋
๋ฌธ์ ์์ ๋์ค๋ ์
๋ ฅ ๋ช
๋ น์ด๋ ๋ ๊ฐ์ง ์ด๋ค.
```bash
๋ช
๋ น์ด 1 - ๋ถ๋ชจ ํด๋ ์ด๋ฆ | ์์ ํด๋ ์ด๋ฆ | 1
๋ช
๋ น์ด 2 - ํด๋ ์ด๋ฆ | ํ์ผ ์ด๋ฆ | 0๋ง์ฝ ๋ช
๋ น์ด 1์ธ ํด๋์ ๋ถ๋ชจ ์์ ๊ด๊ณ ์ฐ์ ์ด๋ฉด, ์ ๋์จํ์ธ๋๋ฅผ ์งํํด์, ๋ถ๋ชจ์ ์์์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ์ด์ด์ผ ํ๋ค. ์ฌ๊ธฐ์ ์ค์ํ ์ ์ ๊ฒฝ๋ก์์ถ์ ํ๋ฉด ์๋๋ค. ์ด์ ๋ ๋ช
๋ น์ด 2 ๋๋ฌธ์ด๋ค.๋ช
๋ น์ด 2๊ฐ ์คํ๋๋ ์์ ์ด ๋๋ฉด, ์ฃผ์ด์ง ํด๋ ์ด๋ฆ์ ํฌํจํด์, ๊ทธ๊ฒ์ ๋ชจ๋ ์์ ํด๋์ ํ์ผ ๊ฐ์ +1, ํ์ฌ ํ์ผ ์ ํ์ด ์ ๊ท ํ์ผ ์ ํ์ด๋ฉด + 1 ์ ์ถ๊ฐํ๋ค.
(2) ์ฟผ๋ฆฌ ์ฒ๋ฆฌํ๊ธฐ
๋ฆฌํ ๋
ธ๋ ํด๋ ๋นผ๊ณ ๋ ๋ค ํ์ ์๋ค. ๋ฐ๋ผ์ br.readLine().split("\") ์ผ๋ก ๋งจ ๋ง์ง๋ง ํด๋ ์ด๋ฆ๋ง ์ฐ๊ณ ๋๋จธ์ง๋ ๋ฒ๋ฆฐ๋ค.
(1) ์๊ฐ๋ณต์ก๋ ๋ถ์ โณ
N๊ณผ M์ด 1000๊ฐ๋ฐ์ ์๋๋ค.
์ผ์ํ ํธ๋ฆฌ์ด๊ณ , ๋ฆฌํ๋
ธ๋์ ํ์ผ์ ์ ๋ถ ๋ฃ๋๋ค๊ณ ํ๋๋ผ๋
ํด๋๋ฅผ ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉฐ ํ์ผ ๊ฐ์ ๋ฐ ํ์ผ ์ ํ์ ์ ๋ฐ์ดํธ ํ๋๋ฐ ์ด $1,000 \times 1,000 = 1,000,000$ ๋ฒ์ ์ฐ์ฐ ํ์ ๋ฐ์ ๋ค์ง ์๋๋ค.
3. ์ฝ๋ ๐
import java.io.*;
import java.util.*;
/*
* ํด๋ ์ ๋ฆฌ (small)* 1. ํด๋์ ํ์ผ ์
๋ ฅ์ผ๋ก unionfind ๋ง๋ค๊ธฐ -> ๊ฒฝ๋ก ์์ถํ์ง ๋ง๊ธฐ
* 2. ํ์ผ ์
๋ ฅ ์ ๋ถ๋ชจ ๋
ธ๋ ํ๊ณ ๊ฐ๋ฉฐ + 1์ฉ ๋ค ํด์ฃผ๊ธฐ
* */
public class Main {
static HashMap<String, Integer> folders = new HashMap<>(); // <ํด๋_์ด๋ฆ, ํด๋ ๋ฒํธ>
static HashMap<String, Integer> files = new HashMap<>(); // <ํ์ผ_์ ํ, ํ์ผ ๋ฒํธ>
static HashMap<Integer, HashSet<Integer>> per_folder_file_cnt = new HashMap<>(); // <ํด๋ ๋ฒํธ, ๋ณด์ ํ์ผ ๋ฒํธ>
static int [] parents; // index = ํด๋ ๋ฒํธ, value = ๋ถ๋ชจ ํด๋ ๋ฒํธ (์ฒ์์ ์๊ธฐ ์์ ์ ๊ฐ๋ฆฌํด)
static int [] accFiles; // ์๊ธฐ ํ์ ๋์ ํ์ผ ์
static int N,M,Q; // ๊ฐ๊ฐ ํด๋์ ๊ฐ์, ํ์ผ์ ๊ฐ์
static int folder_counter = 1;
static int file_counter = 1;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
parents = new int [N+2];
accFiles = new int [N+2];
for(int i = 1; i <= N+1; i++){
parents[i] = i;
per_folder_file_cnt.put(i, new HashSet<>());
}
String [][] inputOrders = new String[N+M][3];
for (int i = 0; i < N+M; i++){
inputOrders[i] = br.readLine().split(" ");
}
Arrays.sort(inputOrders, (row1, row2) -> {
int row1_order = Integer.parseInt(row1[2]);
int row2_order = Integer.parseInt(row2[2]);
return row2_order - row1_order;
});
for (int i = 0; i < inputOrders.length; i++) {
if(inputOrders[i][2].equals("1")) setParents(inputOrders[i][0], inputOrders[i][1]);
else setAccFiles(inputOrders[i][0], inputOrders[i][1]);
}
Q = Integer.parseInt(br.readLine());
StringBuilder answer = new StringBuilder();
for(int i = 0; i < Q; i++){
String [] paths = br.readLine().split("/");
int folder_num = folders.get(paths[paths.length-1]);
answer.append(per_folder_file_cnt.get(folder_num).size()).append(" ").append(accFiles[folder_num]).append("\n");
}
System.out.println(answer);
}
public static void setParents(String parent, String child){
if(folders.getOrDefault(parent, 0) == 0){
folders.put(parent, folder_counter++);
}
if(folders.getOrDefault(child, 0) == 0) {
folders.put(child, folder_counter++);
}
int p_num = folders.get(parent);
int c_num = folders.get(child);
parents[c_num] = p_num;
}
public static void setAccFiles(String folder, String file){
if(files.getOrDefault(file, 0) == 0){
files.put(file, file_counter++);
}
int folder_num = folders.get(folder);
int file_num = files.get(file);
doAcc(folder_num, file_num);
}
public int find(int a){
if(a == parents[a]) return parents[a]; // ๋ถ๋ชจ๊ฐ ์๊ธฐ์์ ์ด๋ผ๋ฉด ๊ทธ๊ฒ์ return else return find (parents[a]);
}
public static void doAcc(int child, int file_type_num){
accFiles[child]++;
per_folder_file_cnt.get(child).add(file_type_num);
if(child == parents[child]) return;
doAcc(parents[child], file_type_num);
}
}
4. ํธ๋ฌ๋ธ ์ํ or ๋ฐฐ์ด ์ ๐
(1) ์ ๋ ฅ์ ๋ถ๋ชจ๋ถํฐ ์์๊น์ง ์์๋๋ก ์ค์ง ์๋๋ค.
Happy-case๋ง ์๊ฐํ๋ ์ต๊ด ๋๋ฌธ์ ์ฒ์์ ํ๋ ธ์๋ค.
ํด๋ ๊ด๊ณ ๋ช
๋ น์ด, ํ์ผ ์ฝ์
๋ช
๋ น์ด๊ฐ ๋ค์ฃฝ๋ฐ์ฃฝ์ผ๋ก ์ฌ ์ ์๋ค. ํ์๋ ํด๋๊ฐ์ ๊ด๊ณ ๋ช
๋ น์ด๊ฐ ์์ ๋, ํด๋ ๋ฒํธ๋ฅผ ๋ง๋ค์ด ์ผ์์ผ๋ก, ๋ค์๊ณผ ๊ฐ์ด ํ์ผ ๋ช
๋ น์ด๊ฐ ์์ ๋ค ๋ชฐ๋ ค์์ ๊ฒฝ์ฐ, ๋ง๋ค์ด์ง์ง ์์ ํด๋๋ฅผ ์ฌ์ฉํ๋ฏ๋ก Null-Pointer ์๋ฌ๊ฐ ๋ฌ๋ค.
3 4
FolderB File1 0
FolderB File3 0
FolderB FolderC 1
main FolderA 1
main FolderB 1
FolderA File1 0
FolderA File2 0
4
main
main/FolderA
main/FolderB
main/FolderB/FolderC
๋ฌธ์ ์์ '์์๋๋ก ์ฃผ์ด์ง๋ค.' ๋ผ๋ ๋ง์ด ์์ผ๋ฉด ํญ์ ์์ ๊ฐ์ edge-case๋ฅผ ์กฐ์ฌํด์ผํ ๊ฒ์ด๋ค.