관리 메뉴

Partially Committed

[λ°±μ€€ 1948] μž„κ³„κ²½λ‘œ (JAVA) λ³Έλ¬Έ

πŸ”₯ Algorithm || λ¬Έμ œν’€μ΄/PS

[λ°±μ€€ 1948] μž„κ³„κ²½λ‘œ (JAVA)

WonderJay 2023. 1. 17. 14:39
728x90
λ°˜μ‘ν˜•
SMALL

문제

μ›”λ“œ λ‚˜λΌλŠ” λͺ¨λ“  λ„λ‘œκ°€ 일방톡행인 λ„λ‘œμ΄κ³ , 싸이클이 μ—†λ‹€. 그런데 μ–΄λ–€ 무수히 λ§Žμ€ μ‚¬λžŒλ“€μ΄ μ›”λ“œ λ‚˜λΌμ˜ 지도λ₯Ό 그리기 μœ„ν•΄μ„œ, μ–΄λ–€ μ‹œμž‘ λ„μ‹œλ‘œλΆ€ν„° 도착 λ„μ‹œκΉŒμ§€ μΆœλ°œμ„ ν•˜μ—¬ κ°€λŠ₯ν•œ λͺ¨λ“  경둜λ₯Ό νƒμƒ‰ν•œλ‹€κ³  ν•œλ‹€.

이 지도λ₯Ό κ·Έλ¦¬λŠ” μ‚¬λžŒλ“€μ€ 사이가 λ„ˆλ¬΄ μ’‹μ•„μ„œ μ§€λ„λ₯Ό κ·Έλ¦¬λŠ” 일을 λ‹€ 마치고 도착 λ„μ‹œμ—μ„œ λͺ¨λ‘ λ‹€ λ§Œλ‚˜κΈ°λ‘œ ν•˜μ˜€λ‹€. κ·Έλ ‡λ‹€κ³  ν•˜μ˜€μ„ λ•Œ 이듀이 λ§Œλ‚˜λŠ” μ‹œκ°„μ€ 좜발 λ„μ‹œλ‘œλΆ€ν„° μΆœλ°œν•œ ν›„ μ΅œμ†Œ λͺ‡ μ‹œκ°„ 후에 λ§Œλ‚  수 μžˆλŠ”κ°€? 즉, λ§ˆμ§€λ§‰μ— λ„μ°©ν•˜λŠ” μ‚¬λžŒκΉŒμ§€ 도착을 ν•˜λŠ” μ‹œκ°„μ„ μ˜λ―Έν•œλ‹€.

μ–΄λ–€ μ‚¬λžŒμ€ 이 μ‹œκ°„μ— λ§Œλ‚˜κΈ° μœ„ν•˜μ—¬ 1뢄도 쉬지 μ•Šκ³  달렀야 ν•œλ‹€. 이런 μ‚¬λžŒλ“€μ΄ μ§€λ‚˜λŠ” λ„λ‘œμ˜ 수λ₯Ό 카운트 ν•˜μ—¬λΌ.

좜발 λ„μ‹œλŠ” λ“€μ–΄μ˜€λŠ” λ„λ‘œκ°€ 0개이고, 도착 λ„μ‹œλŠ” λ‚˜κ°€λŠ” λ„λ‘œκ°€ 0κ°œμ΄λ‹€.

μž…λ ₯

첫째 쀄에 λ„μ‹œμ˜ 개수 n(1 ≤ n ≤ 10,000)이 주어지고 λ‘˜μ§Έ μ€„μ—λŠ” λ„λ‘œμ˜ 개수 m(1 ≤ m ≤ 100,000)이 주어진닀. 그리고 μ…‹μ§Έ 쀄뢀터 m+2μ€„κΉŒμ§€ λ‹€μŒκ³Ό 같은 λ„λ‘œμ˜ 정보가 주어진닀. μ²˜μŒμ—λŠ” λ„λ‘œμ˜ 좜발 λ„μ‹œμ˜ λ²ˆν˜Έκ°€ 주어지고 κ·Έ λ‹€μŒμ—λŠ” 도착 λ„μ‹œμ˜ 번호, 그리고 λ§ˆμ§€λ§‰μ—λŠ” 이 λ„λ‘œλ₯Ό μ§€λ‚˜λŠ”λ° κ±Έλ¦¬λŠ” μ‹œκ°„μ΄ 주어진닀. λ„λ‘œλ₯Ό μ§€λ‚˜κ°€λŠ” μ‹œκ°„μ€ 10,000보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.

그리고 m+3μ§Έ μ€„μ—λŠ” 지도λ₯Ό κ·Έλ¦¬λŠ” μ‚¬λžŒλ“€μ΄ μΆœλ°œν•˜λŠ” 좜발 λ„μ‹œμ™€ 도착 λ„μ‹œκ°€ 주어진닀.

λͺ¨λ“  λ„μ‹œλŠ” 좜발 λ„μ‹œλ‘œλΆ€ν„° 도달이 κ°€λŠ₯ν•˜κ³ , λͺ¨λ“  λ„μ‹œλ‘œλΆ€ν„° 도착 λ„μ‹œμ— 도달이 κ°€λŠ₯ν•˜λ‹€.

좜λ ₯

첫째 μ€„μ—λŠ” 이듀이 λ§Œλ‚˜λŠ” μ‹œκ°„μ„, λ‘˜μ§Έ μ€„μ—λŠ” 1뢄도 쉬지 μ•Šκ³  달렀야 ν•˜λŠ” λ„λ‘œμ˜ μˆ˜κ°€ λͺ‡ κ°œμΈμ§€ 좜λ ₯ν•˜μ—¬λΌ.

예제 μž…λ ₯ 1 

7
9
1 2 4
1 3 2
1 4 3
2 6 3
2 7 5
3 5 1
4 6 4
5 6 2
6 7 5
1 7

예제 좜λ ₯ 1 

12
5

μ–΄λ ΅λ‹€..

 

μΆœλ°œν•˜λŠ” λ„μ‹œμ™€ λ„μ°©ν•˜λŠ” λ„μ‹œκ°€ μ§€μ •λ˜κΈ° λ•Œλ¬Έμ— 일반적인 μœ„μƒ 정렬이 μ•„λ‹ˆλΌ, λͺ©μ μ— 따라 queue 에 λ„£λŠ” λ…Έλ“œλ₯Ό λ‹€λ₯΄κ²Œ ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€.

 

1뢄도 쉬지 μ•Šκ³  달렀야 ν•˜λŠ” λ„λ‘œμ˜ 개수λ₯Ό κ΅¬ν•˜λŠ” λ°μ—λŠ” μ—­λ°©ν–₯ κ·Έλž˜ν”„μ—μ„œ μœ„μƒμ •λ ¬μ„ μˆ˜ν–‰ν•œλ‹€λŠ” νŠΉλ³„ν•œ 아이디어가 ν•„μš”ν•˜λ‹€.

 

이λ₯Ό μœ„ν•΄μ„œ μ •λ°©ν–₯ κ·Έλž˜ν”„ 뿐만이 μ•„λ‹ˆλΌ μ—­λ°©ν–₯ κ·Έλž˜ν”„λ₯Ό λ”°λ‘œ μ„ μ–Έν•΄μ£Όμ–΄μ„œ λ§Œλ“€μ–΄μ£Όμ–΄μ•Ό ν•œλ‹€.

그리고 μ •λ°©ν–₯ κ·Έλž˜ν”„μ—μ„œ μ‹œμž‘ λ„μ‹œλ₯Ό 좜발점으둜 μ§€μ •ν•˜μ—¬ μœ„μƒμ •λ ¬μ„ μˆ˜ν–‰ν•˜λŠ”λ°,

μ€‘μš”ν•œ 것은 μž„κ³„ 경둜 값을 λ„λ‘œλ³„λ‘œ μ €μž₯ν•΄μ£Όμ–΄μ•Ό ν•œλ‹€λŠ” 것이닀.

 

μž„κ³„ 경둜 λ°°μ—΄ path μ—λŒ€ν•˜μ—¬ path[i] λŠ” i 번째 λ„λ‘œμ— λ„λ‹¬ν•˜λŠ” 데에 κ±Έλ¦¬λŠ” μ΅œλŒ€ μ‹œκ°„μ„ λ§ν•œλ‹€.

 

μ •λ°©ν–₯ κ·Έλž˜ν”„μ—μ„œ μœ„μƒμ •λ ¬μ„ μˆ˜ν–‰ν•˜μ—¬ μž„κ³„ 경둜 배열을 μ΄ˆκΈ°ν™”ν•΄μ£Όλ©΄ 이제 μ—­λ°©ν–₯ κ·Έλž˜ν”„μ—μ„œ μœ„μƒμ •λ ¬μ„ μˆ˜ν–‰ν•œλ‹€.

 

μ΄λ•ŒλŠ” 도착 λ„μ‹œκ°€ μ‹œμž‘μ μ΄ λœλ‹€. 

 

  μœ„μƒμ •λ ¬μ„ μˆ˜ν–‰ν•œλ‹€. 예λ₯Ό λ“€μ–΄μ„œ A -> B λΌλŠ” 경둜λ₯Ό νƒμƒ‰ν•˜κ²Œ λœλ‹€λ©΄,

ν˜„μž¬ μž„κ³„ κ²½λ‘œκ°’μΈ path[A] 와 path[B]+ edge λ₯Ό λΉ„κ΅ν•œλ‹€. λ§Œμ•½ 두 값이 λ™μΌν•˜λ‹€λ©΄ A μ—μ„œ B 둜 λ„λ‹¬ν•˜λŠ” 것이 1뢄도 쉬지 μ•Šμ•„μ•Ό ν•˜λŠ” μž„κ³„ κ²½λ‘œλΌλŠ” 것이닀. μ΄λŸ¬ν•œ 경우λ₯Ό μΉ΄μš΄νŒ…ν•΄μ€€λ‹€.

 

  μ€‘μš”ν•œ 것은 queue 에 μƒˆλ‘œμš΄ λ…Έλ“œλ₯Ό 넣을 λ•Œ, μ€‘λ³΅ν•΄μ„œ 넣을 수 μžˆλŠ” κ°€λŠ₯성이 μžˆλ‹€λŠ” 것이닀. 이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ λ³„λ„μ˜ λ°©λ¬Έ 배열을 μ„ μ–Έν•œ λ‹€μŒμ— μ€‘λ³΅ν•œ λ…Έλ“œκ°€ Queue 에 듀어가지 μ•Šλ„λ‘ 방지해주면 λœλ‹€.

 

  그리고 path[λ„μ°©λ„μ‹œ] 와 cntλ₯Ό μ°¨λ‘€λŒ€λ‘œ 좜λ ₯ν•˜λ©΄ λœλ‹€. 쉽지 μ•Šλ„€!

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer stk = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(stk.nextToken()); // node 개수
        stk = new StringTokenizer(br.readLine());
        int m = Integer.parseInt(stk.nextToken()); // edge 개수

        ArrayList<ArrayList<Node>> graph = new ArrayList<>(); // μ •λ°©ν–₯ κ·Έλž˜ν”„
        ArrayList<ArrayList<Node>> reverse_graph = new ArrayList<>(); // μ—­λ°©ν–₯ κ·Έλž˜ν”„

        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<Node>());
            reverse_graph.add(new ArrayList<Node>());
        }
        int[] indegree = new int[n + 1];
        int[] path = new int[n + 1];
        for (int i = 1; i <= m; i++) {
            stk = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(stk.nextToken());
            int b = Integer.parseInt(stk.nextToken());
            int e = Integer.parseInt(stk.nextToken());
            graph.get(a).add(new Node(b, e));
            indegree[b]++;
            reverse_graph.get(b).add(new Node(a, e));
        }
        stk = new StringTokenizer(br.readLine());
        int start = Integer.parseInt(stk.nextToken());
        int end = Integer.parseInt(stk.nextToken());
        //// μž…λ ₯ 끝

        Queue<Integer> q = new LinkedList<>();
        q.offer(start);
        while (!q.isEmpty()) {
            int now = q.poll();
            for (Node cur : graph.get(now)) {
                // μ—°κ²° μ„±λΆ„ 탐색
                indegree[cur.toNode]--;
                path[cur.toNode] = Math.max(path[cur.toNode], path[now] + cur.e);
                if (indegree[cur.toNode] == 0)
                    q.offer(cur.toNode);
            }
        }
        // μ—­μœ„μƒμ •λ ¬
        q.offer(end);
        int cnt = 0;
        boolean[] visited = new boolean[n + 1];
        visited[end] = true;
        while (!q.isEmpty()) {
            int now = q.poll();
            for (Node cur : reverse_graph.get(now)) {
                if (path[now] == path[cur.toNode] + cur.e) {
                    // μž„κ³„ 경둜이면
                    cnt++; // λ„λ‘œ 개수 μΉ΄μš΄νŒ…
                    if (!visited[cur.toNode]) {
                        // 아직 미방문인 λ…Έλ“œλΌλ©΄
                        q.offer(cur.toNode);
                        visited[cur.toNode] = true;
                    }
                }
            }
        }
        System.out.println(path[end]);
        System.out.println(cnt);
    }

    static class Node {
        int toNode;
        int e;

        public Node(int toNode, int e) {
            this.toNode = toNode;
            this.e = e;
        }
    }
}

 

728x90
λ°˜μ‘ν˜•
LIST
Comments