Skip to content

Commit 33c978d

Browse files
committed
Friend network / 심화
1 parent ce7ef04 commit 33c978d

File tree

3 files changed

+166
-0
lines changed

3 files changed

+166
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
const filePath =
2+
process.platform === "linux"
3+
? "/dev/stdin"
4+
: require("path").join(__dirname, "input.txt")
5+
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
6+
const log = console.log
7+
8+
// 1. 재귀 버전
9+
const find = (x, parent) => {
10+
if (parent[x] === x) return x
11+
return (parent[x] = find(parent[x], parent))
12+
}
13+
// 2. 반복문 버전
14+
const find2 = (x, parent) => {
15+
while (parent[x] !== x) {
16+
parent[x] = parent[parent[x]]
17+
x = parent[x]
18+
}
19+
return x
20+
}
21+
22+
// 1. 문자열 크기 비교 방식의 union
23+
// - 작은 값을 부모로 선택하여 트리 밸런싱 시도
24+
// - 문제점: 문자열 비교(a < b)는 사전순 비교라서 예측 불가능한 결과 발생
25+
const union1 = (a, b, parent, size) => {
26+
a = find(a, parent)
27+
b = find(b, parent)
28+
29+
if (a < b) {
30+
parent[b] = a
31+
size[a] += size[b]
32+
return size[a]
33+
} else {
34+
parent[a] = b
35+
size[b] += size[a]
36+
return size[b]
37+
}
38+
}
39+
// 2. 단순 병합 방식의 union -> 항상 첫 번째 루트(a)를 부모로 선택
40+
// -> 작은 값을 부모로 하는 방식보다 트리밸런싱이 비효율적이지만 find에서 경로압축방식을 함께 사용 시 보완된다.
41+
const union2 = (a, b, parent, size) => {
42+
a = find(a, parent)
43+
b = find(b, parent)
44+
if (a !== b) {
45+
parent[b] = a
46+
size[a] += size[b]
47+
}
48+
return size[a]
49+
}
50+
51+
// 3. rank 기반 union -> 트리높이를 저장한 rank 배열을 활용하여 트리밸런싱 문제 해결
52+
const union3 = (a, b, parent, size, rank) => {
53+
a = find(a, parent)
54+
b = find(b, parent)
55+
56+
if (a !== b) {
57+
if (rank[a] < rank[b]) {
58+
// b의 rank가 더 크면 b를 루트로
59+
parent[a] = b
60+
size[b] += size[a]
61+
return size[b]
62+
} else {
63+
// a의 rank가 더 크거나 같으면 a를 루트로
64+
parent[b] = a
65+
size[a] += size[b]
66+
if (rank[a] === rank[b]) {
67+
rank[a]++ // rank가 같을 때만 증가
68+
}
69+
return size[a]
70+
}
71+
}
72+
return size[a]
73+
}
74+
75+
let test = +input[0]
76+
let currentLine = 1
77+
78+
while (test--) {
79+
const F = +input[currentLine]
80+
let parent = {}
81+
let size = {}
82+
let rank = {}
83+
const result = []
84+
85+
for (let i = 1; i <= F; i++) {
86+
const [a, b] = input[currentLine + i].split(" ")
87+
88+
for (let name of [a, b]) {
89+
if (parent[name] === undefined) {
90+
parent[name] = name
91+
size[name] = 1
92+
rank[name] = 0
93+
}
94+
}
95+
96+
result.push(union3(a, b, parent, size, rank))
97+
}
98+
99+
log(result.join("\n"))
100+
currentLine += F + 1
101+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2
2+
3
3+
Fred Barney
4+
Barney Betty
5+
Betty Wilma
6+
3
7+
Fred Barney
8+
Betty Wilma
9+
Barney Betty
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const filePath =
2+
process.platform === "linux"
3+
? "/dev/stdin"
4+
: require("path").join(__dirname, "input.txt")
5+
const input = require("fs").readFileSync(filePath).toString().trim().split("\n")
6+
const log = console.log
7+
8+
// 재귀 버전
9+
const find = (x) => {
10+
if (parent[x] === x) return x
11+
return (parent[x] = find(parent[x]))
12+
}
13+
// 반복문 버전
14+
const find2 = (x) => {
15+
while (parent[x] !== x) {
16+
parent[x] = parent[parent[x]] // 경로 압축
17+
x = parent[x]
18+
}
19+
return x
20+
}
21+
22+
const union = (a, b) => {
23+
a = find(a)
24+
b = find(b)
25+
26+
if (a !== b) {
27+
parent[b] = a
28+
size[a] += size[b] // 집합 크기도 추적
29+
}
30+
return size[a]
31+
}
32+
33+
let test = +input[0]
34+
let currentLine = 1
35+
const result = []
36+
while (test--) {
37+
const F = +input[currentLine]
38+
let parent = {} // 집합 추적
39+
let size = {} // 집합 크기 추적
40+
41+
for (let i = 1; i <= F; i++) {
42+
const [a, b] = input[currentLine + i].split(" ")
43+
44+
for (let name of [a, b]) {
45+
if (parent[name] === undefined) {
46+
parent[name] = name
47+
size[name] = 1
48+
}
49+
}
50+
51+
result.push(union(a, b))
52+
}
53+
54+
log(result.join("\n"))
55+
currentLine += F + 1
56+
}

0 commit comments

Comments
 (0)