다 익스트라 경로 출력 Java - da igseuteula gyeonglo chullyeog Java

최단 경로란?

- 그래프에서 두 정점 사이의 경로들 중에서 간선의 가중치의 합이 최소인 경로

다익스트라 알고리즘

- 하나의 시작 정점에서 끝 정점까지 최단경로를 구하는 알고리즘

예를 들어 아래와 같은 도형이 입력받는다고 가정하자.

다 익스트라 경로 출력 Java - da igseuteula gyeonglo chullyeog Java

이를 입력으로 나타내면 아래와 같다.

6 9 (노드의 개수, 간선의 개수)

0 1 50 (출발지점, 도착지점, 비용)

0 2 30

1 3 30

1 4 70

2 3 20

2 4 40

3 4 10

3 5 80

4 5 30

이를 코드로 구현해보자.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

import java.io.*;

import java.util.*;

public class Main {

static final int INF=987654321// 충분히 큰 값 (무한대)

static int N,E;

static int[][] Graph;

static int[] Dist;

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()); // 노드의 개수

E=Integer.parseInt(st.nextToken()); // 간선의 개수

Graph=new int[N][N];

Dist=new int[N];

for(int i=0;i<N;i++){

for(int j=0;j<N;j++){

if(i==j) Graph[i][j]=0;

else Graph[i][j]=INF;

}

}

for(int i=0;i<E;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][v]=Graph[v][u]=cost;

}

dijkstra(0);

for(int i=0;i<N;i++){

System.out.print(Dist[i]+" ");

}

}

 

INF는 충분히 큰 값으로 무한대를 나타내고, Graph[][] 는 위의 그림을 나타낼 배열로 2차원의 형태로 선언해주고,

Dist[]는 해당 정점으로 방문하기 위한 최솟값을 저장하는 배열이다.

그래프의 초기값의 세팅시 i==j라는 것은 자기자신으로 가는 비용이므로 0이고, 이 외의 비용은 INF로 초기화해준다.

이후, 방향이 없는 그래프 이므로 출발지점과 도착지점에 대한 비용을 양방향으로 세팅해준다. 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

public static void dijkstra(int start){

PriorityQueue<int[]> pq=new PriorityQueue<>((a,b)->a[0]-b[0]);

boolean[] visited=new boolean[N+1];

for(int i=0;i<N;i++){

Dist[i]=INF;

}

Dist[start]=0;

pq.add(new int[]{0,start});

while (!pq.isEmpty()){

int curr[]=pq.poll();

int u=curr[1];

if(visited[u]) continue;

visited[u]=true;

for(int v=0;v<N;v++){

if(Dist[v]>Dist[u]+Graph[u][v]){

Dist[v]=Dist[u]+Graph[u][v];

pq.add(new int[]{Dist[v],v});

}

}

}

}

 

마찬가지로 Dist[]의 배열을 INF로 초기화시켜준 뒤, 시작정점을 방문한 뒤, 우선순위 큐에 삽입한다.

초기에는 0은 1과 2와 연결되어 있으므로 INF와 비교하여 작기 때문에 Dist[1]=50, Dist[2]=30으로 세팅이 된다.

우선순위 큐를 오름차순으로 구현하였기에 Dist[2]=30의 값이 먼저 while에 방문하게 된다.

2에서 연결되어 있는 간선인 3과 4에 Dist[3]=50, Dist[4]=70이 세팅이 된다.

다음에 1에서 갈 수 있는 간선인 3과 4에 Dist[3]=80, Dist[4]=120이지만 이는 if문을 만족하지 못해 초기화되지 못한다.

마찬가지로 오름차순으로 구현하였기에 Dist[3]=50이 먼저 while문에 방문하게 된다.

3에서 연결되어 있는 간선인 4와 5에 Dist[4]=60, Dist[5]=130이 세팅이 된다.

이후 4에서 갈 수 있는 간선인 5에 Dist[5]=90이 더 작으므로 세팅이 된다.

최종적으로 출력된 결과는 아래와 같다.

다 익스트라 경로 출력 Java - da igseuteula gyeonglo chullyeog Java