1. ๋ฌธ์ ์ค๋ช ๐
(1) ๋งํฌ๐
https://www.acmicpc.net/problem/1738
(2) ํด์ค๐ต
๊ฒฝ๋ก์ ๊นกํจ๊ฐ ์์ด์ ๊ฐ์ค์น๊ฐ ๋ง์ด๋์ค
์ธ ๊ฒฝ์ฐ๊ฐ ์๋ค. ๋ฐ๋ผ์ ์ต์ ๊ฒฝ๋ก๋ ๋ฒจ๋ง ํฌ๋
๋ก ๊ตฌํด์ผ ํ๋๋ฐ, ์ฌ๊ธฐ์ ์ ์ฝ ์กฐ๊ฑด์ด ์๋ค.
- 1๏ธโฃ ์ด๋ฒ ๋ฌธ์ ๋ ์ต์ ๊ฐ์ค์น ํฉ์ด ์ต์ ๊ฒฝ๋ก์ธ ์ผ๋ฐ์ ์ธ ๋ฒจ๋ง ํฌ๋ ๋ฌธ์ ์๋ ๋ฌ๋ฆฌ ์ต๋ ๊ฐ์ค์น ํฉ์ด ์ต์ ๊ฒฝ๋ก ์ด๋ค.
- 2๏ธโฃ ๋ฐ๋ผ์ ์ต์ ๊ฒฝ๋ก๋ฅผ ๊ตฌํ ์ ์๋ ๊ฒฝ์ฐ๋ N ๋ฒ์งธ ์ํ๊ณผ์ ์ ๊ฑฐ์ณ๋ ๊ฐ์ค์น์ ํฉ์ด ์ปค์ง๋ ๊ฒฝ๋ก๊ฐ ์๋ ๊ฒฝ์ฐ์ด๋ค.
- 3๏ธโฃํ์ง๋ง ์์ ์ฌ์ดํด์ด 1์์ N๊น์ง์ ๊ฒฝ๋ก์ ์ํฅ์ ์ฃผ์ง ์๋๋ค๋ฉด, ์ต์ ๊ฒฝ๋ก๋ ๊ทธ๋๋ก ์กด์ฌํ๋ ๊ฒ์์ผ๋ก ์๊ด ์๋ค.
2. ์๊ฐ์ ํ๋ฆ: ์ฝ๋๊ฐ ๋์ค๊ธฐ๊น์ง ๐๏ธ
(1) IDEA ๋์ถ๐ก
KEY WORD
: Bellman-ford
, BFS
ํด์ค์์์ 3๋ฒ ์์ ์ฌ์ดํด์ด ์กด์ฌํ๋๋ผ๋, 1์์ N๊น์ง ๊ฐ๋ ๊ฒฝ๋ก ์ค ์ด๋ ํ๋์๋ ์ํฅ์ ์ฃผ์ง ์๋๋ค๋ฉด, ์ต์ ๊ฒฝ๋ก๋ ์กด์ฌํ๋ ๊ฒ์์ผ๋ก ์๊ด ์๋ค.๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ ์ง๊ฐ ๊ด๊ฑด ์ด์๋ค.
์์ ์ฌ์ดํด์ ๋ฐ๊ฒฌํ๋ค๋ฉด, N์๊ฒ ๋ฟ๋์ง๋ง ํ์ธํด์ฃผ๋ฉด ๋๋ค. ํ์๋ ์์ ์ฌ์ดํด์ ๋ฐ๊ฒฌํ ์, ์์ ์ฌ์ดํด์ด ์กด์ฌํ๋ ์ ์ ์์ N๋ฒ ์ ์ ๊น์ง BFS๋ก ๋ฟ๋์ง๋ฅผ ํ์ธํ๋ค.
๋ฐ๋ผ์ ์ด๋ฒ ๋ฌธ์ ์์ ํ์ํ ์๋ฃ๊ตฌ์กฐ๋
- 1๏ธโฃ ๊ฐ์ ๋ฆฌ์คํธ
- 2๏ธโฃ ์ธ์ ๋ฆฌ์คํธ
- 3๏ธโฃ ๊ฑฐ๋ฆฌ ๋ฐฐ์ด
- 4๏ธโฃ to - from ๋ฐฐ์ด (์๊ธฐ ๋ฟ๋ฆฌ ์ฐพ๊ธฐ ๋ฐฐ์ด: ์์ ์๊ฒ ์ค๋ ์ ์ ์ ์ ์ฅ)
์ด ๋๊ฒ ๋ค.
(2) SUDO CODE ๐
- 0๏ธโฃ ์์ ์ ์ํ 4๊ฐ์ง ์๋ฃ๊ตฌ์กฐ ์ ์ธ๊ณผ ์ด๊ธฐํ
- 1๏ธโฃ ๋ฒจ๋งํฌ๋๋ฅผ N-1๋ฒ๊น์ง ์งํ (dist ๋ฐฐ์ด ์ฑ์ฐ๋ฉด์ from-to ๋ฐฐ์ด๋ ์ฑ์ฐ๊ธฐ)
- 2๏ธโฃ ์์ ์ฌ์ดํด ์กด์ฌ ์ฌ๋ถ ํ์ธ
- 3๏ธโฃ ์์ ์ฌ์ดํด์ด ์กด์ฌํ๋ค๋ฉด, ํ ๋ ธ๋๋ถํฐ BFSํ์ฌ N๋ฒ ์ ์ ์ ๋ฟ๋์ง ํ์ธ
- 4๏ธโฃ ๋ฟ์ผ๋ฉด ์ต์ ๊ฒฝ๋ก๊ฐ ๋ ์ ์๋ ์
๋ ฅ์์ผ๋ก
-1
์ ์ถ๋ ฅ - 5๏ธโฃ 2๋ฒ์ ์์ ์ฌ์ดํด์ด ์์ผ๋ฉด
(3) ์๊ฐ๋ณต์ก๋ ๋ถ์ ๐
์ ์ ์ ๊ฐ์ N
(์ต๋ 20,000), ๊ฐ์ ์ ๊ฐ์ E
(100)
์๊ฐ ๋ณต์ก๋: N-1๋ฒ ์ํ + ์์ ์ฌ์ดํด ํ์ธํ๋ฉฐ BFS๋ก N๋ฒ ์ ์ ํ์ธํ๊ธฐ
O(20,000 * 100 + (20,100)) ์๊ฐ๋ณต์ก๋๋ $10^8$๋ณด๋ค ์๋ค
3. ๊ตฌํ ์ฝ๋ ๐
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
Solution solution = new Solution();
solution.solution();
}
}
class Solution {
static int N, M;
static int [][] edge_list;
static ArrayList<Node> [] lists;
static int [] dists, temp;
static int [] where_are_you_from;
static class Node {
int end;
int weight;
public Node (int end, int weight) {
this.end = end;
this.weight = weight;
}
}
public void solution () throws IOException {
input();
if (!bellman_ford()) {
System.out.println(-1);
return;
}
StringBuilder sb = new StringBuilder();
int i = N;
while (i != 0) {
sb.insert(0, i).insert(0, " ");
i = where_are_you_from[i];
}
String answer = sb.toString().trim();
System.out.println(answer);
}
public void input () 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());
dists = new int [N+1];
lists = new ArrayList [N+1];
for (int i = 1; i <= N; i++) {
lists[i] = new ArrayList<>();
}
edge_list = new int[M][3];
where_are_you_from = new int [N+1];
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());
edge_list[i] = new int [] {start, end, weight};
lists[start].add(new Node( end, weight));
}
Arrays.sort(edge_list, (a,b) -> {
if(a[0] == b[0]) {
if(a[1] == b[1]) return a[2] - b[2];
return a[1] - b[1];
}
return a[0] - b[0];
});
}
public boolean bellman_ford () {
Arrays.fill(dists, -(Integer.MAX_VALUE - 1));
dists[1] = 0;
for (int i = 0; i < N; i++) mitigation();
return is_cycle_and_go_to_N();
}
public void mitigation () {
for (int j = 0; j < M; j++) {
int start = edge_list[j][0];
int end = edge_list[j][1];
int weight = edge_list[j][2];
if(dists[start] == - (Integer.MAX_VALUE - 1)) continue;
if(dists[start] + weight > dists[end]) {
dists[end] = dists[start] + weight;
where_are_you_from[end] = start;
}
}
// System.out.println(Arrays.toString(dists));
}
public boolean is_cycle_and_go_to_N(){
for (int j = 0; j < M; j++) {
int start = edge_list[j][0];
int end = edge_list[j][1];
int weight = edge_list[j][2];
if(dists[start] == - (Integer.MAX_VALUE - 1)) continue;
if(dists[start] + weight > dists[end]) {
if(!bfs(start)) return false;
}
}
return true;
}
public boolean bfs (int target_vertex) {
boolean [] isVisited = new boolean[N + 1];
ArrayDeque<Node> aq1 = new ArrayDeque<>();
aq1.add(new Node(target_vertex, 0));
isVisited[target_vertex] = true;
while (!aq1.isEmpty()){
int qSize = aq1.size();
for (int i = 0; i < qSize; i++) {
Node now = aq1.poll();
for (int j = 0; j < lists[now.end].size(); j++) {
Node next = lists[now.end].get(j);
if(!isVisited[next.end]){
if(next.end == N) return false;
aq1.add(next);
isVisited[next.end] = true;
}
}
}
}
return true;
}
}
4. ๋ฐฐ์ด ๊ฒ๋ค ๐ฏ
from-to ๋ฐฐ์ด
์ ๋ํด ๋ฐฐ์ฐ๊ฒ ๋์ด ์ข์๋ค.
์ฒ์์๋ N๋ฒ์์ BFS๋ฅผ ๋๋ฆฌ๋ฉฐ ์ธ์ ์ ์ ๋ค์๊ฒ ์ฌ์ดํด์ด ์๋์ง ํ์ธํ๋๋ฐ, ์ด๊ฒ์ด ์๊ฐ์ด๊ณผ๋ฅผ ์ด๋ํ ๊ฑฐ ๊ฐ๋ค.