[c++] BOJ 1238 :: νŒŒν‹°

λ‚œμ΄λ„ : κ³¨λ“œ 3

κ±Έλ¦° μ‹œκ°„ : 45λΆ„

문제

νŒŒν‹° 문제 λ°”λ‘œκ°€κΈ°

문제

N개의 숫자둜 κ΅¬λΆ„λœ 각각의 λ§ˆμ„μ— ν•œ λͺ…μ˜ 학생이 μ‚΄κ³  μžˆλ‹€.

μ–΄λŠ λ‚  이 Nλͺ…μ˜ 학생이 X (1 ≤ X ≤ N)번 λ§ˆμ„μ— λͺ¨μ—¬μ„œ νŒŒν‹°λ₯Ό 벌이기둜 ν–ˆλ‹€. 이 λ§ˆμ„ μ‚¬μ΄μ—λŠ” 총 M개의 단방ν–₯ λ„λ‘œλ“€μ΄ 있고 i번째 길을 μ§€λ‚˜λŠ”λ° Ti(1 ≤ Ti ≤ 100)의 μ‹œκ°„μ„ μ†ŒλΉ„ν•œλ‹€.

각각의 학생듀은 νŒŒν‹°μ— μ°Έμ„ν•˜κΈ° μœ„ν•΄ κ±Έμ–΄κ°€μ„œ λ‹€μ‹œ κ·Έλ“€μ˜ λ§ˆμ„λ‘œ λŒμ•„μ™€μ•Ό ν•œλ‹€. ν•˜μ§€λ§Œ 이 학생듀은 μ›Œλ‚™ κ²Œμ„λŸ¬μ„œ μ΅œλ‹¨ μ‹œκ°„μ— 였고 κ°€κΈ°λ₯Ό μ›ν•œλ‹€.

이 λ„λ‘œλ“€μ€ 단방ν–₯이기 λ•Œλ¬Έμ— μ•„λ§ˆ 그듀이 였고 κ°€λŠ” 길이 λ‹€λ₯Όμ§€λ„ λͺ¨λ₯Έλ‹€. Nλͺ…μ˜ 학생듀 쀑 였고 κ°€λŠ”λ° κ°€μž₯ λ§Žμ€ μ‹œκ°„μ„ μ†ŒλΉ„ν•˜λŠ” 학생은 λˆ„κ΅¬μΌμ§€ κ΅¬ν•˜μ—¬λΌ.

 

풀이

  • λͺ¨λ“  μ μ—μ„œ XκΉŒμ§€μ˜ μ‹œκ°„κ³Ό Xμ—μ„œ λͺ¨λ“  μ κΉŒμ§€μ˜ μ‹œκ°„μ„ ꡬ해야 ν•œλ‹€.
  • λ‹€μ΅μŠ€νŠΈλΌλŠ” 1개의 μ μœΌλ‘œλΆ€ν„° λͺ¨λ“  μ κΉŒμ§€μ˜ μ΅œλ‹¨ μ‹œκ°„μ„ ꡬ해주기 λ•Œλ¬Έμ—, N번 μˆ˜ν–‰ν•΄μ•Ό μ›ν•˜λŠ” κ²°κ³Όλ₯Ό 얻을 수 μžˆλ‹€.
    • λ‹€μ΅μŠ€νŠΈλΌμ˜ μ‹œκ°„λ³΅μž‘λ„λŠ” ElogE μ΄λ―€λ‘œ NMlogM 의 μ‹œκ°„λ³΅μž‘λ„κ°€ ν•„μš”ν•˜κ³ 
    • 10^7 μ •λ„μ˜ μ‹œκ°„λ³΅μž‘λ„μ΄λ‹€.
  • ν”Œλ‘œμ΄λ“œ 와샬을 써보자.
    • ν”Œλ‘œμ΄λ“œ 와샬은 iλΆ€ν„° jκΉŒμ§€μ˜ 경둜λ₯Ό iλΆ€ν„° k, kλΆ€ν„° jκΉŒμ§€μ˜ κ²½λ‘œμ™€ λΉ„κ΅ν•˜μ—¬ κ°±μ‹ ν•˜λŠ” 방법이닀.
    • ν”Œλ‘œμ΄λ“œ μ™€μƒ¬μ˜ μ‹œκ°„λ³΅μž‘λ„λŠ” V^3 μ΄λ―€λ‘œ 10^9의 μ‹œκ°„λ³΅μž‘λ„κ°€ ν•„μš”ν•˜λ‹€.
    • μ‹œκ°„λ³΅μž‘λ„μ— V만 λ“€μ–΄κ°€κΈ° λ•Œλ¬Έμ— E(κ°„μ„ μ˜ 수)κ°€ 클 λ•Œ μ‚¬μš©ν•˜λ©΄ μ’‹λ‹€.

 

μ½”λ“œ

<λ‹€μ΅μŠ€νŠΈλΌ μ½”λ“œ>

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

int main() {

    // μž…λ ₯
    int N, M, X;
    cin >> N >> M >> X;

    vector<pair<int, int>> path[10001]; // 좜발 => (도착, μ‹œκ°„)
    for (int i = 0; i < M; i++) {
        int start, end, value;
        cin >> start >> end >> value;
        path[start].push_back(make_pair(end, value));
    }

    // μ΄ˆκΈ°ν™”
    int memo[1001][1001];
    fill(&memo[0][0], &memo[1000][1000], 1e9);

    for (int i = 1; i <= N; i++) {
        // i : μ‹œμž‘μ 
        priority_queue<pair<int, int>> que;
        que.push(make_pair(0, i)); // μ‹œκ°„, λ…Έλ“œ
        memo[i][i] = 0;

        while (!que.empty()) {
            pair<int,int> tmp = que.top();
            int time = -tmp.first; int start = tmp.second;
            que.pop();
            if (memo[i][start] < time)
                continue;

            vector<pair<int, int>> canGo = path[start];
            for (int j = 0; j < canGo.size(); j++) {
                int time2 = canGo[j].second; int end = canGo[j].first;
                if (memo[i][end] > memo[i][start] + time2) {
                    memo[i][end] = memo[i][start] + time2;
                    que.push(make_pair(-memo[i][end], end));
                }
            }
        }
    }

    // ν•™μƒλ“€μ˜ μ†Œμš”μ‹œκ°„ μΈ‘μ •
    int res = -1;
    for (int i = 1; i <= N; i++) {
        int value = memo[i][X] + memo[X][i];
        if (value > res)
            res = value;
    }

    cout << res << '\n';
}

 

<ν”Œλ‘œμ΄λ“œ 와샬 μ½”λ“œ>

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>

using namespace std;


int main() {
    // 9μ‹œ μ‹œμž‘ 43λΆ„ 끝
    // λ°©ν–₯이 μžˆλŠ” κ·Έλž˜ν”„
    // 였고 κ°€κΈ° (start => X => start)
    // λ‹€μ΅μŠ€νŠΈλΌ n번 or ν”Œλ‘œμ΄λ“œ 와샬
    // κ°€μž₯ μ˜€λž˜κ±Έλ¦¬λŠ” 학생

    // μ΄ˆκΈ°ν™”
    // memset(memo, 1e9, sizeof(memo));
    int memo[1001][1001];
    fill(&memo[0][0], &memo[1000][1000], 1e9);

    // μž…λ ₯
    int N, M, X;
    cin >> N >> M >> X;

    for (int i = 0; i < M; i++) {
        int start, end, value;
        cin >> start >> end >> value;
        memo[start][end] = value;
    }

    for (int i = 1; i <= N; i++) {
        memo[i][i] = 0; // λŒ€κ°μ„ μ€ 0
    }

    // μ•„λž˜μ˜ μˆœμ„œ μ§€μΌœμ•Ό μ œλŒ€λ‘œ μž‘λ™
    for (int k = 1; k <= N; k++) { // κ±°μ³κ°€λŠ” λ…Έλ“œ
        for (int i = 1; i <= N; i++) { // 좜발
            for (int j = 1; j <= N; j++) { // 도착
                // i,j 와 i,k + k,j 비ꡐ
                memo[i][j] = min(memo[i][j], memo[i][k] + memo[k][j]);
            }
        }
    }

    // ν•™μƒλ“€μ˜ μ†Œμš”μ‹œκ°„ μΈ‘μ •
    int res = -1;
    for (int i = 1; i <= N; i++) {
        int value = memo[i][X] + memo[X][i];
        if (value > res)
            res = value;
    }

    cout << res << '\n';
}

 

<ν…ŒμŠ€νŠΈμΌ€μ΄μŠ€>

5 8 1
1 4 1
4 5 5
1 3 2
3 1 1
4 2 4
2 4 4
5 3 6
3 2 3
=> 21

 

생각해볼 것

  • E(κ°„μ„ μ˜ 수)κ°€ 맀우 크면 ν”Œλ‘œμ΄λ“œ 와샬을 μ΄μš©ν•˜λŠ” 것이 λ‚«λ‹€.
    • λ‹€μ΅μŠ€νŠΈλΌ : EVlogE
    • ν”Œλ‘œμ΄λ“œμ™€μƒ¬ : V^3

 

κ²°κ³Ό

μœ„κ°€ ν”Œλ‘œμ΄λ“œ 와샬, μ•„λž˜κ°€ λ‹€μ΅μŠ€νŠΈλΌμ΄λ‹€.

λ°˜μ‘ν˜•