BellmanFord, SPFA (Shortest Path Faster Algorithm)

ramong2ยท2025๋…„ 9์›” 19์ผ

bellmanFord ์•Œ๊ณ ๋ฆฌ์ฆ˜

๐Ÿ“Œ ๋ฒจ๋งŒโ€“ํฌ๋“œ(Bellmanโ€“Ford) ์•Œ๊ณ ๋ฆฌ์ฆ˜

1. ๊ฐœ์š”

๋‹จ์ผ ์‹œ์ž‘์  ์ตœ๋‹จ ๊ฒฝ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (one - to - all)

๋‹ค์ต์ŠคํŠธ๋ผ(Dijkstra)์™€ ๋‹ฌ๋ฆฌ ์Œ์ˆ˜ ๊ฐ€์ค‘์น˜ ๊ฐ„์„ ์ด ์žˆ์–ด๋„ ๋™์ž‘ ๊ฐ€๋Šฅ

์‹œ๊ฐ„ ๋ณต์žก๋„: O(VยทE) (์ •์  V, ๊ฐ„์„  E)

2. ๋™์ž‘ ์›๋ฆฌ

์‹œ์ž‘ ์ •์  s์—์„œ ๊ฑฐ๋ฆฌ๋ฅผ ์ดˆ๊ธฐํ™”

dist[s] = 0, ๋‚˜๋จธ์ง€ ์ •์ ์€ INF

๋ชจ๋“  ๊ฐ„์„ ์— ๋Œ€ํ•ด V-1๋ฒˆ ๋ฐ˜๋ณตํ•˜์—ฌ ์™„ํ™”(Relaxation)

์™„ํ™”: ๋” ์งง์€ ๊ฒฝ๋กœ๋ฅผ ๋ฐœ๊ฒฌํ•˜๋ฉด ๊ฑฐ๋ฆฌ ๊ฐฑ์‹ 

if (dist[u] + w < dist[v]) dist[v] = dist[u] + w;

ํ•œ ๋ฒˆ ๋” ๋ชจ๋“  ๊ฐ„์„ ์„ ๊ฒ€์‚ฌํ•ด์„œ ๊ฐฑ์‹ ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด

โ†’ ์Œ์ˆ˜ ์‚ฌ์ดํด ์กด์žฌ

3. ์‘์šฉ

k๋ฒˆ์งธ ๋ฐ˜๋ณต ํ›„ dist[v]๋Š” ์‹œ์ž‘์ ์—์„œ v๊นŒ์ง€ ๊ฐ„์„  ์ตœ๋Œ€ k๊ฐœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ์˜๋ฏธ
๋”ฐ๋ผ์„œ V-1๋ฒˆ ๋ฐ˜๋ณตํ•˜๋ฉด ๋ชจ๋“  ๋‹จ์ˆœ ๊ฒฝ๋กœ๋ฅผ ๊ณ ๋ คํ•œ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๋ณด์žฅ

4. ์Œ์ˆ˜ ์‚ฌ์ดํด ๊ฒ€์ถœ

์ตœ๋‹จ ๊ฒฝ๋กœ๋Š” ๊ฐ„์„ ์ด ์ตœ๋Œ€ V-1๊ฐœ

๊ทธ ์ดํ›„์—๋„ ๊ฐฑ์‹ ์ด ๋ฐœ์ƒํ•œ๋‹ค๋ฉด, ์‚ฌ์ดํด์„ ํฌํ•จํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ๋” ์งง์•„์กŒ๋‹ค๋Š” ๋œป

์ด๋Š” ๊ณง ์Œ์ˆ˜ ์‚ฌ์ดํด ์กด์žฌ๋ฅผ ์˜๋ฏธ

5. code


    public class Main {

	static BufferedReader  br = new BufferedReader(new InputStreamReader(System.in));
	static StringBuilder sb = new StringBuilder();
	static StringTokenizer st;

	static class Edge {
		int u;
		int v;
		int cost;

		public Edge(int u, int v, int cost) {
			this.u = u;
			this.v = v;
			this.cost = cost;
		}
	}

	static int N, M;

	static long[] dis;

	static List<Edge> graph = new ArrayList<>();

	public static void main(String[] args) throws IOException {

		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());

		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			int u = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			int cost = Integer.parseInt(st.nextToken());
			graph.add(new Edge(u, v, cost));
		}

		if(!bellmanFord(1)){
			System.out.println(-1);
			System.exit(0);
		}

		for (int i = 2; i <= N; i++) {
			sb.append(dis[i] == Long.MAX_VALUE ? -1 : dis[i]).append("\n");
		}

		System.out.println(sb.toString());
	}

	private static boolean bellmanFord(int start) {
		dis = new long[N + 1];
		Arrays.fill(dis, Long.MAX_VALUE);
		dis[start] = 0;

		for (int i = 1; i <= N - 1; i++) {
			for (Edge edge : graph) {
				if (dis[edge.u] != Long.MAX_VALUE && dis[edge.v] > dis[edge.u] + edge.cost) {
					dis[edge.v] = dis[edge.u] + edge.cost;
				}
			}
		}

		for (Edge edge : graph) {
			if (dis[edge.u] != Long.MAX_VALUE && dis[edge.v] > dis[edge.u] + edge.cost) {
				return false;
			}
		}

		return true;
	}
}

SPFA ์•Œ๊ณ ๋ฆฌ์ฆ˜

1. ๊ฐœ์š”

๋ฒจ๋งŒโ€“ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ตœ์ ํ™” ๋ฒ„์ „

ํ•ต์‹ฌ ์•„์ด๋””์–ด: ๊ฑฐ๋ฆฌ ๋ฐฐ์—ด์ด ์‹ค์ œ๋กœ ๊ฐฑ์‹ ๋œ ์ •์ ๋งŒ ๋‹ค์‹œ ํƒ์ƒ‰

์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์ต์ŠคํŠธ๋ผ๋ณด๋‹ค ๋А๋ฆฌ์ง€๋งŒ, ์Œ์ˆ˜ ๊ฐ„์„ ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์— ์ž์ฃผ ํ™œ์šฉ๋จ

2. ๋™์ž‘ ์›๋ฆฌ

์‹œ์ž‘ ์ •์  s์—์„œ dist[s]=0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ํ(queue)์— ์‚ฝ์ž…

ํ์—์„œ ์ •์ ์„ ๊บผ๋‚ด ๊ทธ ์ •์ ์— ์—ฐ๊ฒฐ๋œ ๊ฐ„์„ ์„ ํ™•์ธ

๋” ์งง์€ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์œผ๋ฉด dist[v]๋ฅผ ๊ฐฑ์‹ ํ•˜๊ณ , ์ •์  v๋ฅผ ํ์— ๋„ฃ์Œ

๋‹จ, v๊ฐ€ ์ด๋ฏธ ํ์— ์žˆ์œผ๋ฉด ์ค‘๋ณต ์‚ฝ์ž…ํ•˜์ง€ ์•Š์Œ

ํ๊ฐ€ ๋นŒ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต

์ฆ‰, ๋ถˆํ•„์š”ํ•œ ์™„ํ™”๋ฅผ ์ค„์ด๊ณ , ํ•„์š”ํ•œ ์ •์ ๋งŒ ๋‹ค์‹œ ํ™•์ธํ•˜๋Š” ๋ฐฉ์‹.

3. ์‹œ๊ฐ„ ๋ณต์žก๋„

์ตœ์•…: O(VยทE) (๋ฒจ๋งŒโ€“ํฌ๋“œ์™€ ๋™์ผ)

ํ‰๊ท : O(E)์— ๊ฐ€๊นŒ์šด ์„ฑ๋Šฅ์„ ๋ณด์ด๋Š” ๊ฒฝ์šฐ๋„ ๋งŽ์Œ

๋”ฐ๋ผ์„œ ์‹ค์ „์—์„œ๋Š” ํ‰๊ท ์ ์œผ๋กœ ๋งค์šฐ ๋น ๋ฅด์ง€๋งŒ, ์ตœ์•… ์„ฑ๋Šฅ ๋ณด์žฅ์ด ์—†๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜

4. ์Œ์ˆ˜ ์‚ฌ์ดํด ๊ฒ€์ถœ

์–ด๋–ค ์ •์ ์ด V๋ฒˆ ์ด์ƒ ํ์— ๋“ค์–ด๊ฐ€๋ฉด ์Œ์ˆ˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค๊ณ  ํŒ๋ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค.
(์ตœ๋‹จ ๊ฒฝ๋กœ๊ฐ€ ๋ฌดํ•œํžˆ ์ค„์–ด๋“œ๋Š” ํ˜„์ƒ)

code

import java.io.*;
import java.util.*;

public class Main {

	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringBuilder sb = new StringBuilder();
	static StringTokenizer st;

	static class Edge {
		int v;
		int cost;

		public Edge(int v, int cost) {
			this.v = v;
			this.cost = cost;
		}
	}

	static int N, M;
	static long[] dis;
	static boolean[] inQueue;
	static int[] count;
	static List<Edge>[] graph;

	public static void main(String[] args) throws IOException {

		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());

		graph = new ArrayList[N + 1];
		for (int i = 1; i <= N; i++) {
			graph[i] = new ArrayList<>();
		}

		for (int i = 0; i < M; i++) {
			st = new StringTokenizer(br.readLine());
			int u = Integer.parseInt(st.nextToken());
			int v = Integer.parseInt(st.nextToken());
			int cost = Integer.parseInt(st.nextToken());
			graph[u].add(new Edge(v, cost));
		}

		if (!SPFA(1)) {
			System.out.println(-1);
			System.exit(0);
		}

		for (int i = 2; i <= N; i++) {
			sb.append(dis[i] == Long.MAX_VALUE ? -1 : dis[i]).append("\n");
		}

		System.out.println(sb.toString());
	}

	private static boolean SPFA(int start) {
		dis = new long[N + 1];
		Arrays.fill(dis, Long.MAX_VALUE);
		inQueue = new boolean[N + 1];
		count = new int[N + 1];

		Queue<Integer> q = new LinkedList<>();
		dis[start] = 0;
		q.add(start);
		inQueue[start] = true;
		count[start]++;

		while (!q.isEmpty()) {
			int u = q.poll();
			inQueue[u] = false;

			for (Edge e : graph[u]) {
				if (dis[u] != Long.MAX_VALUE && dis[e.v] > dis[u] + e.cost) {
					dis[e.v] = dis[u] + e.cost;
					if (!inQueue[e.v]) {
						q.add(e.v);
						inQueue[e.v] = true;
						count[e.v]++;
						if (count[e.v] >= N) {
							return false; // ์Œ์ˆ˜ ์‚ฌ์ดํด ์กด์žฌ
						}
					}
				}
			}
		}

		return true;
	}
}

๋ฐฑ์ค€ 11657 ํƒ€์ž„๋จธ์‹ 
https://www.acmicpc.net/problem/11657

0๊ฐœ์˜ ๋Œ“๊ธ€