티스토리 뷰
https://www.acmicpc.net/problem/2307
2307번: 도로검문
그림 1은 어떤 도시의 주요 지점과 그 지점들 간의 이동시간을 나타낸 그래프이다. 그래프의 노드는 주요 지점을 나타내고 두 지점을 연결한 도로(에지)에 표시된 수는 그 도로로 이동할 때 걸리
www.acmicpc.net
문제
그림 1은 어떤 도시의 주요 지점과 그 지점들 간의 이동시간을 나타낸 그래프이다. 그래프의 노드는 주요 지점을 나타내고 두 지점을 연결한 도로(에지)에 표시된 수는 그 도로로 이동할 때 걸리는 분 단위의 시간을 나타낸다. 두 지점 a와 b를 연결하는 도로는 도로(a,b)로 표시한다.
예를 들어 도로(1,2)와 도로(2,3)를 통하여 지점1에서 지점3으로 갈 때 걸리는 시간은 3분이다. 도로는 모두 양방향이라고 가정하므로 도로(a,b)와 도로(b,a)를 지날 때 걸리는 시간은 항상 같다고 한다.
어떤 범죄용의자가 입력 데이터에 표시된 도시로 진입하여 이 도시를 가장 빠른 시간 내에 빠져나가고자 한다. 그런데 이 사실을 알고 있는 경찰이 어떤 하나의 도로(에지)를 선택하여 이 도로에서 검문을 하려고 한다. 따라서 용의자는 이 도로를 피해서 가장 빠르게 도시를 탈출하고자 한다. 이 경우 경찰이 검문을 위하여 선택하는 도로에 따라서 용의자의 가장 빠른 탈출시간은 검문이 없을 때에 비하여 더 늘어날 수 있다.
문제는 도로검문을 통하여 얻을 수 있는 탈출의 최대 지연시간을 계산하는 것이다. 추가설명은 다음과 같다.
- 두 개의 지점을 직접 연결하는 도로가 있는 경우, 그 도로는 유일하다.
- 도시의 지점(노드)은 1에서 N번까지 N개의 연속된 정수로 표시된다.
- 용의자가 도시에 진입하는 지점은 항상 1번이고 도시를 빠져 나가기 위하여 최종적으로 도달해야하는 지점은 항상 N번 지점이다.
- 용의자는 검문을 피해서 가장 빨리 도시를 빠져나가고자 하고, 경찰은 적절한 도로를 선택하여 이 용이자들의 탈출시간을 최대한 지연시키고자 한다.
- 각 도시 지점 간을 이동하는 시간은 항상 양의 정수이다.
입력 도시의 도로망에 따라서 경찰이 어떤 도로를 막으면 용의자는 도시를 탈출하지 못할 수도 있다. 이 경우 검문으로 인하여 지연시킬 수 있는 탈출시간은 무한대이다. 이 경우에는 -1을 출력해야 한다.
그림 1에서 볼 때 검문이 없을 경우 용의자가 도시를 탈출하는데 걸리는 시간은 4분이다. 만일 경찰이 도로(4,3)을 막으면 그 탈출시간을 지연시킬 수 없으므로 지연시간은 0이다. 만일 도로(2,3)을 막으면, 용의자들이 가장 빠르게 탈출할 수 있는 시간은 5분이므로 탈출지연시간은 1분이고, 도로(3,6)을 막으면 탈출지연시간은 2분이다.
여러분은 입력 데이터에 표시된 도로망을 읽고, 경찰이 한 도로를 막고 검문함으로써 지연시킬 수 있는 최대시간을 정수로 출력하여야한다. 만일 지연효과가 없으면 0을 출력해야하고, 도시를 빠져나가지 못하게 만들 수 있으면(지연시간이 무한대) -1을 출력해야 한다.
유형 : 다익스트라 + 다익스트라에서 경로 구하기
접근 방식
- 문제가 길어서 이해하는 것이 중요하다.
- 결국 도로 한개(간선)을 막았을 때 가장 지연 시간이 긴것을 구하라인데 중요한 것은 비교 대상이 무엇인가이다.
- 비교 대상은 n번째 지점까지의 최소 비용 경로이다. -> 다익스트라 알고리즘을 통해 가장 짧은 경로를 구하자
- 막아야 하는 간선은 무엇일까?
- 모든 간선을 막아보려 한다면 아쉬운 것이다.... 핵심은 가장 지연 시킬수 있어야 하는 것이고 결국 최소 비용 경로에 포함되는 간선을 막는 것이다.
- 즉 첫번 째 다익스트라를 수행할 때 경로 (path[] 배열 사용하여 바로 직전 방문 지점 구하기)를 구하자
- 해당 경로에만 포함 되는 간선들을 한개 씩 막아보고 다익스트라를 수행하자 (최소 비용 경로와 비교하여 가장 큰 값 출력)
전체 코드
import java.util.*;
import java.io.*;
public class Main {
static int n = 0;
static int m = 0;
static ArrayList<Node>[] graph;
static int[] path;
public static void main(String[] args) throws Exception {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb =new StringBuilder();
StringTokenizer st = new StringTokenizer(bf.readLine(), " ");
n = Integer.parseInt(st.nextToken());
m = Integer.parseInt(st.nextToken());
graph = new ArrayList[n+1];
for(int i=1;i<=n;i++){
graph[i] = new ArrayList<>();
}
for(int i=1;i<=m;i++){
st = new StringTokenizer(bf.readLine(), " ");
int x = Integer.parseInt(st.nextToken());
int y = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
graph[x].add(new Node(y,v,i));
graph[y].add(new Node(x,v,i));
}
int result = 0;
int shortestPath = findPath();
for(int i=2;i<=n;i++){
int tmp = banAndFind(i);
if(tmp == Integer.MAX_VALUE){
System.out.println(-1);
return;
}
if(tmp - shortestPath > result){
result = tmp - shortestPath;
}
}
System.out.println(result);
bf.close();
}
static int findPath(){
path = new int[n+1];
PriorityQueue<Node> pq = new PriorityQueue<>(
(x,y) -> x.c - y.c
);
int[] dis = new int[n+1];
for(int i=2;i<=n;i++){
dis[i] = Integer.MAX_VALUE;
}
pq.add(new Node(1,0,0));
while(!pq.isEmpty()){
Node cur = pq.poll();
for(Node next : graph[cur.v]){
if(dis[next.v] > dis[cur.v] + next.c){
dis[next.v] = dis[cur.v] + next.c;
path[next.v] = cur.v;
pq.add(new Node(next.v,dis[next.v],next.num));
}
}
}
return dis[n];
}
static int banAndFind(int ban){
PriorityQueue<Node> pq = new PriorityQueue<>(
(x,y) -> x.c - y.c
);
int[] dis = new int[n+1];
for(int i=2;i<=n;i++){
dis[i] = Integer.MAX_VALUE;
}
pq.add(new Node(1,0,0));
while(!pq.isEmpty()){
Node cur = pq.poll();
for(Node next : graph[cur.v]){
if((cur.v == ban && next.v == path[ban]) || (cur.v == path[ban] && next.v == ban)){
continue;
}
if(dis[next.v] > dis[cur.v] + next.c){
dis[next.v] = dis[cur.v] + next.c;
pq.add(new Node(next.v,dis[next.v],next.num));
}
}
}
return dis[n];
}
}
class Node{
int v;
int c;
int num;
Node(int v,int c,int num){
this.v = v;
this.c = c;
this.num = num;
}
}
'알고리즘 > 백준' 카테고리의 다른 글
백준 21922(학부 연구생 민상) - java (1) | 2023.12.04 |
---|---|
백준 17845 (수강 과목) - java (0) | 2023.11.29 |
백준 14728 (벼락치기) - java (0) | 2023.11.28 |
백준 23254 (나는 기말고사형 인간이야) - java (0) | 2023.11.28 |
백준 3987 (보이저 1호) - java (1) | 2023.11.27 |
- Total
- Today
- Yesterday
- 백준 #12014 #주식 #자바 #java
- 백준 #2580 #스도쿠
- 백준 #25195 #yes or yes #java #자바
- 백준 #
- 백준 #1584 #게임 #java #자바
- 17394
- 백준 #1759 #암호 만들기
- 백준 #16973 #직사각형 탈출
- 백준 #인구 이동 #16234
- 백준 #25603 #짱해커 이동식 #java #자바
- 백준 #1727 #커플 만들기 #자바 #java
- 백준
- 백준 #28140 #빨강~ 빨강~ 파랑! 파랑! 달콤한 솜사탕! #java #자바
- 백준 #다리 만들기 #2146
- Java
- 백준 #15686 #치킨 배달
- 백준 #13549 #숨바꼭질3
- 자바 #JAVA
- 자바
- 백준 #18405 #경쟁적 전염
- 백준 #1325 #효율적인 해킹
- 백준 #2636 #치즈
- 백준 #4963 #섬의 개수
- 백준 #치즈 #2638
- 17218
- 백준 #17940 #주식 #자바 #java
- 백준 #5721 #사탕 줍기 대회 #java #자바
- 백준 #3980 #선발 명단
- 백준 #1987 #알파벳 #자바 #java
- 백준 #14863 #서울에서 경산까지 #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 | 29 | 30 | 31 |