1504번

2023. 2. 5. 11:02·CS 이론/알고리즘
728x90

https://www.acmicpc.net/problem/1504

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net

오늘도 한 감자 했다...어제와 비슷한 문제였는데...문제를 좀만 더 잘 읽을걸 그랬다.

문제의 내용은 간단하다 주어지는 특정한 정점 두개를 반드시 지나는 최단경로를 구하라는 것이다.

여기서 내가 실수 한 것은 문제에서 양방향의 간선이 주어졌다는 것이다....저번 1753번 문제를 생각하면서 풀다보니...양방향은 생각도 못했다....그래서 몇 시간 동안 뭔 난리를 친건지...그래서 결과 적으로 양방향의 간선을 넣어주자마자 통과했다.

 

이 문제의 풀이 방법은 간단하다. 주어지는 특정정점들까지의 최단경로를 다익스트라로 탐색하고 이 것들의 합을 구하는 것이다.

식으로 설명하자면, f(a,b)라는 a에서 b로 가는 최단경로를 찾는 다익스트라 알고리즘 함수가 있다고 했을 때,

f(1,a)+f(a,b)+f(b,N)과 f(1,b)+f(b,a)+f(a,N)의 값중에 작은 값을 고르는 것이다.

위 식은 1-a-b-N, 1-b-a-N의 두 가지 경로를 의미한다.

그리고 만약 위의 탐색에서 특정 노드에 접근 하는 경로가 없으면 -1로 반환하면 된다.

나머지는 여러글에서 올라오듯 다익스트라 알고리즘 그대로이다.

 

나의 경우에는 Graph클래스를 정의해서 findMin메서드로 최단 경로를 반환하게 만들었다.

여기서 중요한 것은 우선순위 큐를 사용하는 것이다.

 

정답 코드는 아래와 같다.

 

package backjoon.b1504;

import java.util.LinkedList;
import java.util.PriorityQueue;
import java.io.*;
import java.util.*;
public class b1504 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int E = Integer.parseInt(st.nextToken());
        Graph g = new Graph(N);
        for(int i=0; i<E; i++){
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());
            g.addEdge(u,v,w);//간선 추가
        }
        st = new StringTokenizer(br.readLine());
        int node1 = Integer.parseInt(st.nextToken());
        int node2 = Integer.parseInt(st.nextToken());
        int min=g.findMin(node1,node2);//최단경로 반환

        System.out.println(min);
    }
}
class Graph{
    int N;
    LinkedList<Node>[] adj;
    PriorityQueue<Node> queue;
    int[] distance;
    public Graph(int N){
        this.N = N;
        adj = new LinkedList[N+1];
        for(int i=0; i<=N; i++){
            adj[i]=new LinkedList<>();
        }
        queue = new PriorityQueue<>();
        distance = new int[N+1];
        Arrays.fill(distance,Integer.MAX_VALUE);
    }
    public void addEdge(int u, int v, int w){
        adj[u].add(new Node(v,w));
        adj[v].add(new Node(u,w));
    }
    public int bfs(int start, int end){
        Arrays.fill(distance,Integer.MAX_VALUE);//각각의 경로 탐색과정(bfs(1,node1),bfs(node1,node2)...)에 이전 탐색이 영향을 주지 않기 위해서 초기화한다.
        queue.add(new Node(start,0));
        distance[start]=0;
        while (!queue.isEmpty()){
            Node node = queue.poll();

            if(node.weight>distance[node.end])continue;

            for (Node nextNode : adj[node.end]) {
                int dis = node.weight+nextNode.weight;//현재 노드의 누적된 가중치와 다음 노드의 가중치를 더한 값
                if(dis<distance[nextNode.end]){//다음 노드의 저장되어있는 누적 가중치와 현재 다른 경로로 구한 가중치를 비교
                    distance[nextNode.end]=dis;
                    queue.add(new Node(nextNode.end, dis));
                }
            }
        }
        return distance[end];
    }
    public int findMin(int node1,int node2){
        int min = Integer.MAX_VALUE;
        int min2 = Integer.MAX_VALUE;
        if(bfs(1, node1)<Integer.MAX_VALUE && bfs(node1, node2)<Integer.MAX_VALUE && bfs(node2, N)<Integer.MAX_VALUE){
            min = bfs(1, node1) + bfs(node1, node2) + bfs(node2, N);
        }
        if ((bfs(1, node2)<Integer.MAX_VALUE && bfs(node2, node1)<Integer.MAX_VALUE && bfs(node1, N)<Integer.MAX_VALUE)) {
            min2= bfs(1, node2) + bfs(node2, node1) + bfs(node1, N);
        }
        if(min==Integer.MAX_VALUE && min2==Integer.MAX_VALUE){
            return -1;
        }//특정 노드에 접근할 수 없을 때 -1 반환
        return Math.min(min,min2);
    }// 1-a-b-N, 1-b-a-N의 경로 중 최단 경로 반환
}
class Node implements Comparable<Node>{
    int weight;
    int end;

    public Node(int end, int weight ) {
        this.end = end;
        this.weight = weight;
    }

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

 

 

728x90

'CS 이론 > 알고리즘' 카테고리의 다른 글

11657번(벨만 포드)  (0) 2023.02.08
13549번  (0) 2023.02.06
1753번  (0) 2023.02.04
1707번  (0) 2023.02.03
2206번  (0) 2023.02.02
'CS 이론/알고리즘' 카테고리의 다른 글
  • 11657번(벨만 포드)
  • 13549번
  • 1753번
  • 1707번
Bello's
Bello's
개발하는 벨로
  • Bello's
    벨로의 개발일지
    Bello's
  • 전체
    오늘
    어제
    • 분류 전체보기 (199)
      • 노예 일지 (7)
        • 스타트업 노예일지 (3)
      • CS 이론 (81)
        • 학과 수업 (4)
        • 알고리즘 (64)
        • 시스템 프로그래밍 (3)
        • 데이터 통신 (1)
        • 운영체제 (2)
        • 데이터베이스 (1)
      • project (3)
      • 나는 감자다. (4)
      • Spring (27)
      • 모각코 (45)
        • 절개와지조(모각코) (7)
        • 어쩌다보니 박준태가 조장이조 (11)
        • 어쩌다보니 박준태가 또 조장이조 (12)
      • LikeLion🦁 (20)
      • 캘리포니아 감자 (4)
      • OpenSource Contribute (1)
      • 우아한테크벨로 (1)
        • 프리코스 회고록 (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    DFS
    오블완
    8기
    회고록
    어렵다
    프리코스
    절개와지조
    JPA
    타임리프
    티스토리챌린지
    누적합
    감자
    백준
    자바
    모각코
    나는 감자
    Spring
    그래프 순회
    BFS
    뛰슈
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Bello's
1504번
상단으로

티스토리툴바