티스토리 뷰
https://www.acmicpc.net/problem/22868
22868번: 산책 (small)
코로나로 인하여 확찐자가 되버려 오늘부터 산책을 하려고 한다. 이를 위해 산책할 경로를 정하려고 한다. 현재 있는 곳 $S$에서 출발하여 $S$와 다른 곳인 $E$를 찍고 다시 $S$로 돌아오는 경로로
www.acmicpc.net

문제
코로나로 인하여 확찐자가 되버려 오늘부터 산책을 하려고 한다. 이를 위해 산책할 경로를 정하려고 한다.
현재 있는 곳 에서 출발하여 와 다른 곳인 를 찍고 다시 돌아오는 경로로 만들려고 한다. 산책을 할 때 이미 갔던 정점을 또 가기 싫어 에서 로 올 때 에서 로 가는 도중에 방문한 정점을 제외한 다른 정점으로 이동하려고 한다. 또한 산책 거리가 긴 것을 싫어하여 에서 로 가는 가장 짧은 거리와 에서 로 가는 가장 짧은 거리를 원한다.
정점 에서 정점 로 이동할 때, 가장 짧은 거리의 경로가 여러개 나올 수 있다. 그 중, 정점 에서 정점 로 이동한 경로를 나열했을 때, 사전순으로 가장 먼저 오는 것을 선택한다.
예를 들어, 정점 1에서 정점 2로 이동한다고 했을 때, 가장 짧은 거리의 경로가 1 4 3 2와 1 3 4 2가 있다고 가정을 해보자. 두 개의 경로중 사전순으로 먼저 오는 것은 1 3 4 2이므로 정점 1에서 정점 2로 가는 최단 경로 중 두 번째 것을 선택한다.
이와 같이 산책 경로를 정할 때, 산책 전체 경로의 거리 에서 로 가는 거리 + 에서 로 가는 거리)를 구해보자.
유형 : BFS
접근 방식
- 출발지에서 도착지까지 가고 다시 도착지에서 출발지까지 이동해야 한다.
- 사실 문제에서 접근 해야하는 순서를 알려줬다.
- 정점 에서 정점 로 이동한 경로를 나열했을 때, 사전순으로 가장 먼저 오는 것
- 즉 S에서 E로 이동 시에는 작은 순서의 정점을 차례대로 밞아야 한다.
- 우선 그래프의 각 간선들을 오름차순으로 정렬한다.
- 그리고 S -> E 로 이동하는 BFS 를 수행한다.
- 여기서 각 노드 클래스에 list를 이용한 path 변수를 통해 지나온 경로의 정점을 저장한다.
- E에서 S로 이동하기 전에 앞서 구한 경로의 정점을 모두 방문 처리한다.
- 그리고 E -> S로의 BFS를 수행한다.
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static int n = 0;
static int m = 0;
static boolean[] v;
static int s,e;
static ArrayList<Integer>[] graph;
static int result = 0;
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
graph = new ArrayList[n+1];
v = new boolean[n+1];
for(int i =1 ; i <= n ; i++){
graph[i] = new ArrayList<>();
}
for(int i = 1; i <= m ; i++){
st = new StringTokenizer(br.readLine(), " ");
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
graph[x].add(y);
graph[y].add(x);
}
for(int i = 1 ; i <= n ; i++){
Collections.sort(graph[i]);
}
st = new StringTokenizer(br.readLine(), " ");
s = Integer.parseInt(st.nextToken());
e = Integer.parseInt(st.nextToken());
List<Integer> fp = bfs(s,e);
v = new boolean[n+1];
for(int next : fp){
if(next == s || next == e)
continue;
v[next] = true;
}
List<Integer> sp = bfs(e,s);
HashSet<Integer> set = new HashSet<>();
set.addAll(sp);
set.addAll(fp);
result = set.size();
System.out.println(result);
br.close();
}
static List<Integer> bfs(int x,int end){
v[x] = true;
Queue<Node> q = new ArrayDeque<>();
Node start = new Node(x);
start.path.add(x);
q.add(start);
while(!q.isEmpty()){
Node cur = q.poll();
if(cur.x == end){
return cur.path;
}
for(int next : graph[cur.x]){
if(!v[next]){
v[next] = true;
Node nextNode = new Node(next);
nextNode.path.addAll(cur.path);
nextNode.path.add(next);
q.add(nextNode);
}
}
}
return null;
}
static class Node{
int x;
List<Integer> path = new ArrayList<>(20);
Node(int x){
this.x = x;
}
}
}
'알고리즘 > 백준' 카테고리의 다른 글
| 백준 18224 (미로에 갇힌 건우) - java (0) | 2024.03.31 |
|---|---|
| 백준 12763 (지각하면 안 돼) - java (0) | 2024.03.27 |
| 백준 1486 (등산) - java (0) | 2024.03.18 |
| 백준 17281 (⚾) - ja (0) | 2024.02.27 |
| 백준 2001 (보석 줍기) - java (0) | 2024.02.26 |
- Total
- Today
- Yesterday
- 백준 #2636 #치즈
- 백준 #1325 #효율적인 해킹
- 자바 #JAVA
- 17394
- 올해보다
- 백준 #18405 #경쟁적 전염
- 17218
- 백준 #14863 #서울에서 경산까지 #java #자바
- 자바
- 백준 #2580 #스도쿠
- 백준 #인구 이동 #16234
- 백준 #12014 #주식 #자바 #java
- 백준 #1759 #암호 만들기
- 행복합시다.
- 백준 #15686 #치킨 배달
- 백준 #
- 백준 #5721 #사탕 줍기 대회 #java #자바
- 백준 #1987 #알파벳 #자바 #java
- 백준 #13549 #숨바꼭질3
- 백준 #17940 #주식 #자바 #java
- 백준 #다리 만들기 #2146
- 백준 #25603 #짱해커 이동식 #java #자바
- 백준 #16973 #직사각형 탈출
- 백준 #1584 #게임 #java #자바
- 백준 #4963 #섬의 개수
- Java
- 백준 #치즈 #2638
- 백준 #3980 #선발 명단
- 백준
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |