Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[241129] BOJ 16166 서울의 지하철 #1029

Merged
merged 1 commit into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
static Map<Long, List<Edge>> adjMap;
static int N;
static long dest;

public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());

adjMap = new HashMap<>();

//PQ를 통한 탐색
//해당 번호(Long)가 갈 수 있는 엣지를 담는 맵을 통해 임의 접근
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int cnt = Integer.parseInt(st.nextToken());
long pre = Long.parseLong(st.nextToken());
for (int j = 0; j < cnt - 1; j++) {
long cur = Long.parseLong(st.nextToken());
Edge edge = new Edge(i, pre, cur);
List<Edge> edgeList = adjMap.getOrDefault(pre, new ArrayList<>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 이렇게 getOrDefault로 new 할당하는 방식은 새롭네요

edgeList.add(edge);
adjMap.put(pre, edgeList);
//양방향
edge = new Edge(i, cur, pre);
edgeList = adjMap.getOrDefault(cur, new ArrayList<>());
edgeList.add(edge);
adjMap.put(cur, edgeList);
pre = cur;
}
}
dest = Long.parseLong(br.readLine());
System.out.println(dest == 0 ? 0 : dijkstra());
}

private static int dijkstra() {
PriorityQueue<Info> pq = new PriorityQueue<>();
List<Edge> edgeList = adjMap.getOrDefault(0L, new ArrayList<>());
for (int i = 0; i < edgeList.size(); i++) {
Edge edge = edgeList.get(i);
Info info = new Info(edge.num, edge.v, 0);
info.set.add(info);
pq.offer(info);
}
int res = -1;
while (!pq.isEmpty()) {
Info info = pq.poll();

if (info.v == dest) {
res = info.cnt;
break;
}

List<Edge> edges = adjMap.getOrDefault(info.v, new ArrayList<>());
for (int i = 0; i < edges.size(); i++) {
Edge edge = edges.get(i);

List<Edge> nexts = adjMap.getOrDefault(edge.u, new ArrayList<>());
Info next = new Info(edge.num, edge.u, info.cnt + ((edge.num == info.num) ? 0 : 1));
if (!info.set.add(next)) continue;
next.set = new HashSet<>(info.set);
pq.offer(next);
for (int j = 0; j < nexts.size(); j++) {
Edge nextEdge = nexts.get(j);
next = new Info(nextEdge.num, nextEdge.v, next.cnt + ((nextEdge.num == next.num) ? 0 : 1));
Set<Info> set = new HashSet<>(info.set);
if (set.add(next)) {
next.set = set;
pq.offer(next);
}
}
}
}
return res;
}
}

//이동 경로 정보 저장
class Info implements Comparable<Info> {
int num;
long v;
int cnt;
Set<Info> set = new HashSet<>(); //isv

public Info(int num, long v, int cnt) {
this.num = num;
this.v = v;
this.cnt = cnt;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Info info = (Info) o;
return num == info.num && v == info.v;
}

@Override
public int hashCode() {
return Objects.hash(num, v);
}

@Override
public int compareTo(Info o) {
return Integer.compare(this.cnt, o.cnt);
}
}

class Edge {
int num; //호선
long v, u; //v -> u;

public Edge(int num, long v, long u) {
this.num = num;
this.v = v;
this.u = u;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# 소스코드

```Java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
static Map<Long, List<Edge>> adjMap;
static int N;
static long dest;

public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
N = Integer.parseInt(br.readLine());

adjMap = new HashMap<>();

//PQ를 통한 탐색
//해당 번호(Long)가 갈 수 있는 엣지를 담는 맵을 통해 임의 접근
for (int i = 0; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int cnt = Integer.parseInt(st.nextToken());
long pre = Long.parseLong(st.nextToken());
for (int j = 0; j < cnt - 1; j++) {
long cur = Long.parseLong(st.nextToken());
Edge edge = new Edge(i, pre, cur);
List<Edge> edgeList = adjMap.getOrDefault(pre, new ArrayList<>());
edgeList.add(edge);
adjMap.put(pre, edgeList);
//양방향
edge = new Edge(i, cur, pre);
edgeList = adjMap.getOrDefault(cur, new ArrayList<>());
edgeList.add(edge);
adjMap.put(cur, edgeList);
pre = cur;
}
}
dest = Long.parseLong(br.readLine());
System.out.println(dest == 0 ? 0 : dijkstra());
}

private static int dijkstra() {
PriorityQueue<Info> pq = new PriorityQueue<>();
List<Edge> edgeList = adjMap.getOrDefault(0L, new ArrayList<>());
for (int i = 0; i < edgeList.size(); i++) {
Edge edge = edgeList.get(i);
Info info = new Info(edge.num, edge.v, 0);
info.set.add(info);
pq.offer(info);
}
int res = -1;
while (!pq.isEmpty()) {
Info info = pq.poll();

if (info.v == dest) {
res = info.cnt;
break;
}

List<Edge> edges = adjMap.getOrDefault(info.v, new ArrayList<>());
for (int i = 0; i < edges.size(); i++) {
Edge edge = edges.get(i);

List<Edge> nexts = adjMap.getOrDefault(edge.u, new ArrayList<>());
Info next = new Info(edge.num, edge.u, info.cnt + ((edge.num == info.num) ? 0 : 1));
if (!info.set.add(next)) continue;
next.set = new HashSet<>(info.set);
pq.offer(next);
for (int j = 0; j < nexts.size(); j++) {
Edge nextEdge = nexts.get(j);
next = new Info(nextEdge.num, nextEdge.v, next.cnt + ((nextEdge.num == next.num) ? 0 : 1));
Set<Info> set = new HashSet<>(info.set);
if (set.add(next)) {
next.set = set;
pq.offer(next);
}
}
}
}
return res;
}
}

//이동 경로 정보 저장
class Info implements Comparable<Info> {
int num;
long v;
int cnt;
Set<Info> set = new HashSet<>(); //isv

public Info(int num, long v, int cnt) {
this.num = num;
this.v = v;
this.cnt = cnt;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Info info = (Info) o;
return num == info.num && v == info.v;
}

@Override
public int hashCode() {
return Objects.hash(num, v);
}

@Override
public int compareTo(Info o) {
return Integer.compare(this.cnt, o.cnt);
}
}

class Edge {
int num; //호선
long v, u; //v -> u;

public Edge(int num, long v, long u) {
this.num = num;
this.v = v;
this.u = u;
}
}
```

# 소요시간

1시간 30분

# 알고리즘

> 다익스트라, BFS

# 풀이

# BOJ 16166 서울의 지하철

1. Map에 역번호, List<Edge> 형식으로 해당 역에서 갈 수 있는 모든 역 (다른 호선도 가능)을 저장
2. Edge는 호선, v -> u 의 정보 저장
3. Info는 호선, 역, 환승 횟수, isv역할의 Set<Info> 저장, 다익스트라를 사용하기 위해 환승 횟수를 기준으로 비교
4. 초기에 인접 역들을 양방향으로 Edge를 만들고 Map에 세팅해준다.
5. 다익스트라 알고리즘을 통해 0번역에서 탐색 시작
6. HashSet을 통해 방문 여부를 확인하므로 equals, hashCode재정의 (호선, 역)
7. 탐색 시 해당 (호선, 역)에서 갈 수 있는 인접 `역`을 먼저 탐색 후 해당 `역`의 다른 호선을 추가하는 방식으로 탐색
8. 같은 호선이라면 0 다른 호선이라면 1을 더해주어 환승 카운팅
9. 탐색 도중 목적지에 도착하면 res를 환승 횟수로 갱신하고 break;
10. 최종적으로 res를 반환하여 출력 (res의 초기값은 -1으로 목적지 도달 불가 시 -1 반환)

---