티스토리 뷰

rust 연습 삼아 간단한 알고리즘 문제들을 하루 한 문제 정도 하기로 결정했습니다.

시간 날 때 rust로 사이드 프로젝트도 간단히 해볼 생각입니다. (아이디어 생각은 해놨지만 언제 할런지....)

rust로 ps 자체에 대해 접근하기는 꽤 까다롭습니다. 입출력 속도 문제, 타입 문제 등이 있어 몇 개 풀어본 결과 괜찮은 방식은

use std::io::{stdin, Read};
use std::fmt::Write;

fn main() {

    let mut input = String::new();  
    let mut output = String::new();  
    stdin().read\_to\_string(&mut input).unwrap();  

    let mut input = input.split\_ascii\_whitespace();

    // n,m 입력 받기  
    let n = input.next().unwrap().parse::<usize>().unwrap();  
    let m = input.next().unwrap().parse::<usize>().unwrap();

    // ~~ res 연산

    writeln!(output, "{}", res).unwrap();

    print!("{}", output);
}

이런 식으로 입출력을 한 번에 처리하는 게 가장 깔끔했습니다.

입력 시 next로 공백, 줄바꿈 기준으로 다음 글자 있는 지 판단하고, 출력 시, output에 기록된 모든 내용을 한 번에 출력시킵니다.

입력 시 필요한 type은 parse:: 으로 해당 type에 맞게 parsing 시켜주면 됩니다.

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

간단히 다익스트라 + 우선순위 큐 기반의 문제를 풀어보면 다음과 같습니다.

N이 최대 30만이므로, 노드 개수가 N일 때 다익스트라 + 우선순위 큐 이용 시 O(N log N) 이므로 충분히 통과합니다.

2d vector로 graph를 구성해도 되지만, 그냥 hashmap 으로 구성했습니다. 해시 계산이 없는 2d vector가 더 빠르지만 연습삼아 hashmap으로 접근했습니다.

다익스트라 + 우선순위 큐 로직은 다음과 같습니다.

1. 전체 dist 배열을 INF로 초기화

2. 그래프 구성 시 (연결된 노드 번호, 엣지 가중치) 로 구성

3. 우선순위 큐에 (0, 시작점) 넣기 (min heap으로 구성)

4. 시작점으로부터 탐색 시작

5. 큐에서 하나씩 빼면서

6. 연결된 노드들 중 방문 안 했고, 현재까지 체크된 길이와 현재 엣지가 업데이트될 수 있으면 업데이트시키고 큐에 넣고 방문 체크

7. 5,6번 반복

코드는 다음과 같습니다.

use std::io::{stdin, Read};
use std::fmt::Write;
use std::collections::{BinaryHeap, HashMap};
use std::cmp::Reverse;

// n : 노드 개수, start : 시작점, graph : 그래프 정보
// return : 거리 정보 
fn dijkstra(n: usize, start: usize, graph: HashMap<usize, Vec<(usize, usize)>>) -> Vec<usize> {
    // 거리 초기화
    let mut dist: Vec<usize> = Vec::new();
    let mut visited: Vec<bool> = Vec::new();
    for _ in 0..n {
        dist.push(usize::MAX);
        visited.push(false);
    }

    // 우선순위 큐 : Reverse로 min heap 으로 동작시킴
    // pq 원소 : (거리, 노드)
    let mut pq: BinaryHeap<Reverse<(usize, usize)>> = BinaryHeap::new();
    pq.push(Reverse((0usize, start)));
    visited[start] = true;

    // 우선순위 큐 + 다익스트라 
    while !pq.is_empty() {
        let ele = pq.pop().unwrap().0;
        let cost = ele.0;
        let node = ele.1;

        if let Some(v) = graph.get(&node) {
            for ele in v.iter() {
                let next_node = (*ele).0;
                let next_cost = cost + (*ele).1;

                if visited[next_node] {
                    continue;
                }

                if next_cost < dist[next_node] {
                    dist[next_node] = next_cost;
                    pq.push(Reverse((next_cost, next_node)));
                    visited[next_node] = true;
                }
            }
        }
    }

    dist
}

fn main() {
    let mut input = String::new();
    let mut output = String::new();
    stdin().read_to_string(&mut input).unwrap();

    let mut input = input.split_ascii_whitespace();

    let n = input.next().unwrap().parse::<usize>().unwrap();
    let m = input.next().unwrap().parse::<usize>().unwrap();
    let k = input.next().unwrap().parse::<usize>().unwrap();
    let x = input.next().unwrap().parse::<usize>().unwrap() - 1;

    // 문제 상 거리 항상 1
    let mut graph: HashMap<usize, Vec<(usize, usize)>> = HashMap::new();
    for _ in 0..m {
        let a = input.next().unwrap().parse::<usize>().unwrap() - 1;
        let b = input.next().unwrap().parse::<usize>().unwrap() - 1;

        if !graph.contains_key(&a) {
            graph.insert(a, vec![]);
        } 
        if let Some(v) = graph.get_mut(&a) {
            v.push((b, 1usize));
        }
    }

    // 계산 
    let dist = dijkstra(n, x, graph);
    let mut res: Vec<usize> = Vec::new();

    for i in 0..dist.len() {
        if dist[i] == k {
            res.push(i+1);
        }
    }

    if res.len() == 0 {
        writeln!(output, "{}", -1).unwrap();
    } else {
        for r in res.iter() {
            writeln!(output, "{}", *r).unwrap();
        }
    }

    print!("{}", output);
}

'알고리즘 > 백준' 카테고리의 다른 글

백준 11438 LCA 2 C++  (3) 2024.03.07
백준 3665 최종 순위 Rust  (0) 2024.02.12
백준 19237 어른 상어 C++  (1) 2024.01.14
백준 22289 큰 수 곱셈 (3) C++  (1) 2024.01.11
백준 11025 요세푸스 문제 3  (0) 2024.01.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/12   »
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
글 보관함