1. ๋ฌธ์ ์ค๋ช ๐
๋ฌธ์ ๋ฅผ ๋ณด๋ฉฐ, ์ฐพ์๋ธ ์กฐ๊ฑด์ ๋ค์ 3
๊ฐ์ง ์๋ค.
1๏ธโฃ ์ต์ ๊ฐ์์ ํ์ ์ ๋ณต๊ตฌํ๋ผ
2๏ธโฃ ๋ชจ๋ ์๋ก ๋ค๋ฅธ 2 ๋์ ์ปดํจํฐ๊ฐ ๊ต์ ์ด ๊ฐ๋ฅํด์ผ ํ๋ค.
3๏ธโฃ ์ํผ ์ปดํจํฐ์์ ๋ค๋ฅธ ์ปดํจํฐ๋ก์ ํต์ ์ต์ ๋น์ฉ์ ๋ณต๊ตฌ ์ด์ ๊ณผ ๊ฐ์์ผ ํ๋ค.
๋ฌธ์ ๋ฅผ ํ๋ฉฐ ๋๋ ์ ์,
3๏ธโฃ ๋๋ฌธ์ 1๏ธโฃ์ ์์ผ๋ ๋ง๋ ํ ์กฐ๊ฑด์ด ๋์๋ค. 3๏ธโฃ์ ๋ง์กฑ์ํค๋ ค๋ฉด๋ค์ต์คํธ๋ผ
๋ฅผ ํ์ฉํด์, ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ์์ผ ํ๊ณ , ๊ทธ ์ต๋จ ๊ฒฝ๋ก์ ์ฌ์ฉ๋ ํ์ ๋ณด๋ค ๊ฐ์๋ฅผ ๋ ์ค์ผ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. (์ค์ด๋ฉด, ์ด๋ค ์ปดํจํฐ์๋ ์ํผ์ปดํจํฐ๊ฐ ๋๋ฌํ์ง ๋ชปํ๋ค.) 2๏ธโฃ ๋ํ ๋ค์ต์คํธ๋ผ๋ฅผ ํ์ฉํ๋ฉด, ์ต์ ์ํผ ์ปดํจํฐ๋ฅผ ๋งค๊ฐ๋ก ๋ชจ๋ ๊ต์ ํ ์ ์๊ธฐ์ ๋ฐ๋ก ๊ตฌํํด์ผ ํ๋ ์กฐ๊ฑด์ด ์๋๋ค. ๋ฐ๋ผ์ ๋ค์ต์คํธ๋ผ๋ฅผ ํ๋ฉฐ ๊ฑฐ์ณ๊ฐ ๊ฒฝ๋ก๋ฅผ ๊ธฐ์ตํ๋ ๋ฌธ์ ์ด๋ค.
2. ๊ตฌํ ๋ฐฉ๋ฒ ๐๏ธ
KEY WORD
: DIJKSTRA
- 0๏ธโฃ ์ธ์ ๋ฆฌ์คํธ ๊ตฌํ ์ฉ ํด๋์ค์ธ
Node
์ ๋ค์ต์คํธ๋ผ์ฉ ํด๋์ค์ธDist
๋ฅผ ๋๋ ์ ๊ตฌํํ๋ค.- ์ด๋ DIST์๋ ๊ฑฐ์ณ์จ ๊ฐ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๋
HashSet<Edge> edge
๋ฅผ ๊ตฌํํด ๋๋๋ค. HashSet<Edge> edge
๋ HashMap์ ๋๋ฑ์ฑ์ ์ํ์ฌ hashCode์ equals๋ฅผ overrideํ์ฌ ๊ตฌํํด ๋๋๋ค.- ์ต๋จ๊ฑฐ๋ฆฌ ๋ฐฐ์ด๋
Dist
๋ฅผ ์๋ฃํ์ผ๋ก ๊ตฌํํ๋ค.
- ์ด๋ DIST์๋ ๊ฑฐ์ณ์จ ๊ฐ์ ์ ๋ณด๋ฅผ ์ ์ฅํ๋
- 1๏ธโฃ ๋ค์ต์คํธ๋ผ๋ฅผ ์งํํ๋ค. ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด์
dist(๋์ฐฉ์ง๊น์ง์ ์ต๋จ๊ฑฐ๋ฆฌ)
๊ฐ ๊ฐฑ์ ๋ ๋๋ง๋ค, ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด์Edge Set
๋ ๊ฐฑ์ ํ๋ค. (๋ง์ฝdist[B] > dist[A] + A โ B์ ๊ฐ์ ๋น์ฉ
์ผ๋ก ๊ฐฑ์ ๋์๋ค๋ฉด,dist[B].edge
๋ ์๋ ๊ฐ์ ๋น์ฐ๊ณ ,dist[A].edge
+new Edge(A, B)
๋ก ์ฑ์ด๋ค.) - 2๏ธโฃ๋ค์ต์คํธ๋ผ๊ฐ ๋๋ ๋ค์๋ ์ต๋จ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด์ ๋๋ฉฐ, ๋ชจ๋ Edge๋ฅผ ์ ์ฒด HashSet์ ๋ฃ๋๋ค. (์ค๋ณต ์ ๊ฑฐ + ๋ชจ๋ ๊ฐ์ ์ ํ ๊ณณ์ ์ ์ฅ)
- 3๏ธโฃ ์ ์ฒด HashSet์ Size์ ๊ฐ ๊ฐ์ ์ ์ถ๋ ฅํ๋ค.
(1) ์๊ฐ๋ณต์ก๋ ๋ถ์ ๐
์ ์ ์ ์๋ฅผ V
, ๊ฐ์ ์ ์๋ฅผ E
๋ผ๊ณ ํ ๋,
๊ธฐ๋ณธ ๋ค์ต์คํธ๋ผ ์๊ฐ ๋ณต์ก๋ $O(V \log E)$
- ์ฒซ ๋ฐ๋ณต์๋ ์ต๋ 0๊ฐ์ ๊ฐ์ ์ ์ญ์ ํ๊ณ , ์ต๋ 1 ๊ฐ์ ๊ฐ์ ์ ์ฝ์ ํ๋ค.
- ๋ ๋ฒ์งธ ๋ฐ๋ณต์๋ ์ต๋ 1๊ฐ์ ๊ฐ์ ์ ์ญ์ ํ๊ณ , ์ต๋ 2๊ฐ์ ๊ฐ์ ์ ์ฝ์ ํ๋ค.
- ...
V
๋ฒ์งธ ๋ฐ๋ณต์๋ ์ต๋ $V-1$๊ฐ์ ๊ฐ์ ์ ์ญ์ ํ๊ณ , $V$๊ฐ์ ๊ฐ์ ์ ์ฝ์ ํ๋ค.
์ด $O(V^{2})$
์ฆ $O(V \log E) + O(V^{2})$ ๋ก ์๊ฐ๋ณต์ก๋๋ $O(V^{2})$ ๋ค.
๋ด ํ์ด๊ฐ ํต๊ณผํ ์ด์ ๋ ์๋ง, ์ ์ ์ ๊ฐ์๊ฐ ์ต๋ 1000๊ฐ๋ผ์ ์ธ ๊ฒ ๊ฐ๋ค.
3. ์ฝ๋ ์๊ฐ ๐
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static int N,M;
static ArrayList<Node> [] lists;
static Dist [] dists;
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());
lists = new ArrayList[N + 1];
for (int i = 1; i < N + 1; i++) {
lists[i] = new ArrayList<>();
}
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int weight = Integer.parseInt(st.nextToken());
lists[start].add(new Node(end, weight));
lists[end].add(new Node(start, weight));
}
dijkstra();
HashSet<Edge> sum = new HashSet<>();
StringBuilder ans = new StringBuilder();
for (int i = 1; i < N + 1; i++) {
sum.addAll(dists[i].routes);
}
ans.append(sum.size()).append("\n");
for (Edge now : sum){
ans.append(now.start).append(" ").append(now.end).append("\n");
}
System.out.println(ans.toString());
}
public static void dijkstra () {
dists = new Dist[N + 1];
for (int i = 1; i < N + 1; i++) {
dists[i] = new Dist(i);
}
dists[1].dist = 0;
PriorityQueue<Dist> pq = new PriorityQueue<>(Comparator.comparingInt(o -> o.dist));
pq.add(new Dist(1,0));
while(!pq.isEmpty()){
Dist now = pq.poll();
if(now.dist != dists[now.idx].dist) continue;
for (int i = 0; i < lists[now.idx].size(); i++) {
Node next = lists[now.idx].get(i);
if(dists[next.idx].dist > dists[now.idx].dist + next.w) {
dists[next.idx].dist = dists[now.idx].dist + next.w;
dists[next.idx].routes.clear();
dists[next.idx].routes.addAll(dists[now.idx].routes);
dists[next.idx].routes.add(new Edge(now.idx, next.idx));
pq.add(new Dist(next.idx, dists[next.idx].dist, dists[next.idx].routes));
}
}
}
}
}
class Dist {
int idx;
int dist;
HashSet<Edge> routes;
public Dist (int i) {
this.idx = i;
this.dist = Integer.MAX_VALUE;
routes = new HashSet<>();
}
public Dist (int i, int dist){
this.idx = i;
this.dist = dist;
}
public Dist (int i, int dist, HashSet<Edge> prev){
this.idx = i;
this.dist = dist;
routes = new HashSet<>();
routes.addAll(prev);
}
public String toString() {
return "[" + idx + ", " + dist + ", " + routes + "]";
}
}
class Node {
int idx;
int w;
public Node (int idx, int w) {
this.idx = idx;
this.w = w;
}
}
class Edge {
int start;
int end;
public Edge (int start, int end) {
this.start = start;
this.end = end;
}
@Override
public int hashCode(){
return this.start + this.end;
}
@Override
public boolean equals(Object obj) {
if(obj.getClass() != this.getClass()) return false;
Edge o = (Edge) obj;
return o.start == this.start && o.end == this.end;
}
}
4. ๋ฐฐ์ด ๊ฒ๋ค ๐ฏ
์ฒซ ํ์ด๋ ๋ง์ฝ 'ํ์ ๊ณ์ฐํ ์ต๋จ ๊ฑฐ๋ฆฌ ๊ฐ์ค์น๊ฐ ๊ฐ์ผ๋ฉด, ๊ฐ์ ์ ์ ๊ฒ ์ด ๋ ์์ผ๋ก dist๋ฅผ ๊ฐฑ์ ํ๋ค'๋ ์๋ฏธ์ ์ฝ๋๋ฅผ ์์ฑํ๋ค. ํ์ง๋ง, ํด๋น ์ฝ๋๋ ๋ฌด์๋ฏธํ๊ฒ ๊ณ์ฐ ์๊ฐ๋ง ์ก์๋จน๋ ์ฝ๋์ด๋ค. ์๋ํ๋ฉด, ๋ฌด์จ ๊ฒฝ๋ก๋ฅผ ์ฐ๋ ์ฌ์ฉ๋ ์ ์ฒด ๊ฐ์ ์ ๊ฐ์์ ์ด์งํผ 1๊ฐ๋ง ๋ํด์ง๊ธฐ ๋๋ฌธ์ด๋ค.
![image-20250117234351671](../../../../../Documents/GitHub/dalcheonroadhead-github-blog/dalcheonroadhead.github.io/images/[๋ฐฑ์ค] 2211 ๋คํธ์ํฌ ๋ณต๊ตฌ/image-20250117234351671.png)
ํด๋น ์์์์๋ B,C๊ฐ ๋จผ์ ๋ฐฉ๋ฌธ ๋ ๊ฒ์ด๊ณ , ๋ค์์ A๋ฅผ ๋ฐฉ๋ฌธํ ์ฐจ๋ก๋ค. ์ฐ์ ์์ ํ ๊ตฌํ์ ๋ฐ๋ผ์ ์ถ๋ฐ์ง์์ ๋ฐ๋ก A๋ก ๊ฐ๋ 3์ด ๋จผ์ ๋จ๊ฒ ์ง๋ง, ์ฐ๋ฆฌ๋ 1 โ 1 โ 1์ด ๋จผ์ ํ์์ ๋์ค๊ณ ๋ค์ ๊ฐ์ 1๊ฐ ์ง๋ฆฌ 3์ด ํ์์ ๋์จ๋ค๊ณ ํด๋ณด์.
if(dists[next.idx].dist == dists[now.idx].dist + next.w &&
dists[next.idx].routes.size() > dists[now.idx].routes.size() + 1) {
dists[next.idx].routes.clear();
dists[next.idx].routes.addAll(dists[now.idx].routes);
dists[next.idx].routes.add(new Edge(now.idx, next.idx));
}
๊ทธ๋ ค๋ฉด ๋ด๊ฐ ์ ์ ํด๋น ์ฝ๋์ ๋ฐ๋ผ, (์ถ๋ฐ์ง,B)โ (B,C) โ (C,A)์ ํ๊ธฐ ๋๊ณ (์ถ๋ฐ์ง,A)๋ก dist[A]๋ ๊ฐฑ์ ๋ ๊ฒ์ด๋ค. ๊ทผ๋ฐ ๋์ค์ ํฉ์น๋ฉด, ๋ ๊ฒฝ์ฐ์ ์ ๋ชจ๋ ๊ฐ์ ์ 3๊ฐ๋ง ์ฌ์ฉํ๋ค.
[A, B], [B, C]. [C, A] ์ด๋ , [A,B], [B,C], [A,C] ์ด๋ ๋ง์ด๋ค.