알고리즘(백준 등) 공부
SWEA 5684. [Professional] 운동
posite
2026. 4. 30. 11:54
1~N 번호로 이루어있는 N개의 건물이 있고 이 건물들을 잇는 시작점, 도착점, 거리 정보가 주어지는 M개의 일방통행 도로가 있어 시작점부터 시작해서 다시 시작점으로 돌아오는 사이클 중 가장 작은 사이클의 도로의 길이의 합을 구하는 문제이다. 최소 사이클을 찾기 위해 다익스트라 알고리즘을 이용하여 풀이하였다.
먼저, 도로의 정보를 Map에 저장한다.
Map<Integer, List<Road>> map = new HashMap<>();
for(int i=1; i<=n; i++) {
map.put(i, new ArrayList<>());
}
for(int i=0; i<m; i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken()), e = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
map.get(s).add(new Road(e, c));
}
시작점을 1부터 N까지 시작점으로 삼고 다익스트라 알고리즘을 적용하여 우선순위 큐에 도착점, 누적 이동 길이 정보를 가진 Road를 넣음으로서 이동하면서 가장 작은 사이클을 찾는다. 이미 방문했던 곳이라도 더 짧은 길이거나 시작점에 도착하는 길 이라면 그 길을 선택하여 해당 건물에 도착한다. 시작점에 도착하면 해당 방법이 시작점으로 돌아오는 가장 작은 사이클이 되며 누적된 도로 길이의 합을 업데이트해준다.
int min = Integer.MAX_VALUE;
for(int i=1; i<=n; i++) {
PriorityQueue<Road> pq = new PriorityQueue<>(new Comparator<Road>() {
@Override
public int compare(Road o1, Road o2) {
return o1.c - o2.c;
}
});
int[] visited = new int[n+1];
Arrays.fill(visited, Integer.MAX_VALUE);
visited[i] = 0;
for(Road next: map.get(i)) pq.add(new Road(next.e, next.c));
while(!pq.isEmpty()) {
Road current = pq.remove();
if(current.e == i) {
min = Math.min(min, current.c);
break;
}
if(current.c > visited[current.e]) continue;
visited[current.e] = current.c;
for(Road next: map.get(current.e)) {
if(visited[next.e] > current.c + next.c || next.e == i) {
pq.add(new Road(next.e, current.c+ next.c));
}
}
}
}
sb.append(min == Integer.MAX_VALUE ? -1 : min).append('\n');
결과 코드는 다음과 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
for (int tc = 1; tc <= T; tc++) {
sb.append('#').append(tc).append(' ');
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken()), m = Integer.parseInt(st.nextToken());
Map<Integer, List<Road>> map = new HashMap<>();
for(int i=1; i<=n; i++) {
map.put(i, new ArrayList<>());
}
for(int i=0; i<m; i++) {
st = new StringTokenizer(br.readLine());
int s = Integer.parseInt(st.nextToken()), e = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
map.get(s).add(new Road(e, c));
}
int min = Integer.MAX_VALUE;
for(int i=1; i<=n; i++) {
PriorityQueue<Road> pq = new PriorityQueue<>(new Comparator<Road>() {
@Override
public int compare(Road o1, Road o2) {
return o1.c - o2.c;
}
});
int[] visited = new int[n+1];
Arrays.fill(visited, Integer.MAX_VALUE);
visited[i] = 0;
for(Road next: map.get(i)) pq.add(new Road(next.e, next.c));
while(!pq.isEmpty()) {
Road current = pq.remove();
if(current.e == i) {
min = Math.min(min, current.c);
break;
}
if(current.c > visited[current.e]) continue;
visited[current.e] = current.c;
for(Road next: map.get(current.e)) {
if(visited[next.e] > current.c + next.c || next.e == i) {
pq.add(new Road(next.e, current.c+ next.c));
}
}
}
}
sb.append(min == Integer.MAX_VALUE ? -1 : min).append('\n');
}
br.close();
System.out.print(sb);
}
static class Road {
int e, c;
Road(int e, int c) {
this.e = e;
this.c = c;
}
}
}