https://www.acmicpc.net/problem/1916
Gold V
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
private static int[][] graph;
private static int[] least_costs;
private static boolean[] visited;
private static int N;
private static class Node implements Comparable<Node> {
private final int end, cost;
Node(int end, int cost) {
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Node o) {
return Integer.compare(this.cost, o.cost);
}
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(bf.readLine());
int M = Integer.parseInt(bf.readLine());
//setup for edges
graph = new int[N+1][N+1];
least_costs = new int[N+1];
visited = new boolean[N+1];
for (int i = 1; i <= N; ++i) {
least_costs[i] = Integer.MAX_VALUE;
for (int j = 1; j <= N; ++j) {
graph[i][j] = -1;
}
}
StringTokenizer st;
for (int i = 0; i < M; ++i) {
st = new StringTokenizer(bf.readLine(), " ");
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
if (graph[start][end] == -1 || cost < graph[start][end]) {
graph[start][end] = cost;
}
}
st = new StringTokenizer(bf.readLine(), " ");
int start_city = Integer.parseInt(st.nextToken());
int dst_city = Integer.parseInt(st.nextToken());
dijkstra(start_city);
System.out.print(least_costs[dst_city]);
}
private static void dijkstra(int start_city) {
PriorityQueue<Node> q = new PriorityQueue<>();
q.add(new Node(start_city, 0));
least_costs[start_city] = 0;
//dijkstra
while (!q.isEmpty()) {
int next_city = q.poll().end;
if (!visited[next_city]) {
visited[next_city] = true;
for (int i = 1; i <= N; ++i) {
if (graph[next_city][i] != -1) {
int cost = least_costs[next_city] + graph[next_city][i];
if (cost < least_costs[i]) {
least_costs[i] = cost;
q.add(new Node(i, cost));
}
}
}
}
}
}
}
그냥 dijkstra algorithm 구현이다. 다만 좀 오래 걸렸는데 이유는...
dijkstra를 너무 오랜만에 구현해서(...)
이 링크를 보고 복습했다. 예전에 C로 구현을 했을 때 직접 minheap를 만들어가지고(...) 세부적으로 구현했었는데 이번에는 중간에 최소비용이 변동된채로 추가하고 싶어도 이를 즉각 수정하는 것이 API상 불가능하기 때문에 그냥 priority queue에 넣는 형태로 구현을 함. 메모리가 좀 낭비되지만, semantic 적으로 크게 문제는 되지 않는다.
Read/WriteBuffer
이랑 StringTokenizer
쓰느라 좀 오래 걸렸다. 그래도 이제는 다 이해되는 상황.
다시보니 1번의 이유가 가장 컸던것 같다.
위는 adjacency matrix를 썼지만, 처음에 구상한 방식은 위와 같지 않았으며 이는 밑부분 참고. 이것도 정답인 답이며, LinkedList
랑 ArrayList
를 활용했다. 메모리랑 시간이 앞의 것보다 좀 더 많이 잡아먹는다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
private static ArrayList<LinkedList<Node>> edges;
private static int[] least_costs;
private static boolean[] visited;
private static int N;
private static class Node implements Comparable<Node> {
private final int end, cost;
Node(int end, int cost) {
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Node o) {
return Integer.compare(this.cost, o.cost);
}
}
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(bf.readLine());
int M = Integer.parseInt(bf.readLine());
//setup for edges
edges = new ArrayList<>(N+1);
least_costs = new int[N+1];
visited = new boolean[N+1];
edges.add(null);
for (int i = 1; i <= N; ++i) {
least_costs[i] = Integer.MAX_VALUE;
edges.add(i, new LinkedList<>());
}
StringTokenizer st;
for (int i = 0; i < M; ++i) {
st = new StringTokenizer(bf.readLine(), " ");
int start = Integer.parseInt(st.nextToken());
int end = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
edges.get(start).add(new Node(end, cost));
}
st = new StringTokenizer(bf.readLine(), " ");
int start_city = Integer.parseInt(st.nextToken());
int dst_city = Integer.parseInt(st.nextToken());
dijkstra(start_city);
System.out.print(least_costs[dst_city]);
}
private static void dijkstra(int start_city) {
PriorityQueue<Node> q = new PriorityQueue<>();
q.add(new Node(start_city, 0));
least_costs[start_city] = 0;
//dijkstra
while (!q.isEmpty()) {
int next_city = q.poll().end;
if (!visited[next_city]) {
visited[next_city] = true;
for (Node edge : edges.get(next_city)) {
int cost = least_costs[next_city] + edge.cost;
if (cost < least_costs[edge.end]) {
least_costs[edge.end] = cost;
q.add(new Node(edge.end, cost));
}
}
}
}
}
}