Here's a Rust program that calculates the shortest path between two nodes in a weighted, undirected graph using Dijkstra's algorithm. The graph is represented as an adjacency matrix read from a text file.

```rust
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::usize;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() != 4 {
        eprintln!("Usage: {} <input_file> <source_node_id> <destination_node_id>", args[0]);
        return;
    }

    let input_file = &args[1];
    let source_node_id: usize = args[2].parse().expect("Invalid source node ID");
    let destination_node_id: usize = args[3].parse().expect("Invalid destination node ID");

    let graph = read_graph_from_file(input_file).expect("Error reading graph from file");

    let (shortest_path, total_weight) = dijkstra(&graph, source_node_id, destination_node_id);

    println!(
        "Shortest path: {:?}\nTotal weight: {}",
        shortest_path, total_weight
    );
}

fn read_graph_from_file(file_path: &str) -> Result<Vec<Vec<usize>>, Box<dyn std::error::Error>> {
    let file = File::open(file_path)?;
    let reader = BufReader::new(file);
    let mut graph = vec![];

    for line in reader.lines() {
        let line = line?;
        let row: Vec<usize> = line.split_whitespace()
                                  .map(|x| x.parse().unwrap())
                                  .collect();
        graph.push(row);
    }

    Ok(graph)
}

fn dijkstra(
    graph: &[Vec<usize>],
    source_node_id: usize,
    destination_node_id: usize,
) -> (Vec<usize>, usize) {
    let n = graph.len();
    let mut visited = vec![false; n];
    let mut distances = vec![usize::MAX; n];
    let mut previous_nodes = vec![None; n];

    distances[source_node_id] = 0;

    for _ in 0..n {
        let current_node = find_min_distance_node(&distances, &visited);
        if current_node == destination_node_id {
            break;
        }

        visited[current_node] = true;

        for neighbor in 0..n {
            let weight = graph[current_node][neighbor];
            if weight > 0 && !visited[neighbor] {
                let new_distance = distances[current_node].saturating_add(weight);
                if new_distance < distances[neighbor] {
                    distances[neighbor] = new_distance;
                    previous_nodes[neighbor] = Some(current_node);
                }
            }
        }
    }

    let shortest_path = reconstruct_path(previous_nodes, source_node_id, destination_node_id);
    let total_weight = distances[destination_node_id];

    (shortest_path, total_weight)
}

fn find_min_distance_node(distances: &[usize], visited: &[bool]) -> usize {
    let mut min_distance = usize::MAX;
    let mut min_index = 0;

    for (index, (&distance, &is_visited)) in distances.iter().zip(visited).enumerate() {
        if !is_visited && distance < min_distance {
            min_distance = distance;
            min_index = index;
        }
    }

    min_index
}

fn reconstruct_path(
    previous_nodes: Vec<Option<usize>>,
    source_node_id: usize,
    destination_node_id: usize,
) -> Vec<usize> {
    let mut path = vec![];
    let mut current_node = destination_node_id;

    while current_node != source_node_id {
        path.push(current_node);
        current_node = previous_nodes[current_node].unwrap();
    }

    path.push(source_node_id);
    path.reverse();

    path
}
```

To run the program, save it as `dijkstra.rs` and compile it using `rustc dijkstra.rs`. Then, you can execute the compiled binary with the input file path and source and destination node IDs:

```sh
$ ./dijkstra input.txt 0 4
Shortest path: [0, 2, 3, 4]
Total weight: 9
```

The input file should contain the adjacency matrix of the graph, where each row is a space-separated list of weights. For example, the following input file represents a graph with five nodes (0-4) and weighted edges between them:

```
0 10 1 0 0
10 0 0 5 1
1 0 0 2 0
0 5 2 0 2
0 1 0 2 0
```
다음은 Dijkstra의 알고리즘을 사용하여 가중치가 있는 방향이 없는 그래프에서 두 노드 사이의 최단 경로를 계산하는 Rust 프로그램입니다. 그래프는 텍스트 파일에서 읽은 인접 행렬로 표현됩니다.

```rust
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::usize;

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() != 4 {
        eprintln!("Usage: {} <input_file> <source_node_id> <destination_node_id>", args[0]);
        return;
    }

    let input_file = &args[1];
    let source_node_id: usize = args[2].parse().expect("Invalid source node ID");
    let destination_node_id: usize = args[3].parse().expect("Invalid destination node ID");

    let graph = read_graph_from_file(input_file).expect("Error reading graph from file");

    let (shortest_path, total_weight) = dijkstra(&graph, source_node_id, destination_node_id);

    println!(
        "Shortest path: {:?}\nTotal weight: {}",
        shortest_path, total_weight
    );
}

fn read_graph_from_file(file_path: &str) -> Result<Vec<Vec<usize>>, Box<dyn std::error::Error>> {
    let file = File::open(file_path)?;
    let reader = BufReader::new(file);
    let mut graph = vec![];

    for line in reader.lines() {
        let line = line?;
        let row: Vec<usize> = line.split_whitespace()
                                  .map(|x| x.parse().unwrap())
                                  .collect();
        graph.push(row);
    }

    Ok(graph)
}

fn dijkstra(
    graph: &[Vec<usize>],
    source_node_id: usize,
    destination_node_id: usize,
) -> (Vec<usize>, usize) {
    let n = graph.len();
    let mut visited = vec![false; n];
    let mut distances = vec![usize::MAX; n];
    let mut previous_nodes = vec![None; n];

    distances[source_node_id] = 0;

    for _ in 0..n {
        let current_node = find_min_distance_node(&distances, &visited);
        if current_node == destination_node_id {
            break;
        }

        visited[current_node] = true;

        for neighbor in 0..n {
            let weight = graph[current_node][neighbor];
            if weight > 0 && !visited[neighbor] {
                let new_distance = distances[current_node].saturating_add(weight);
                if new_distance < distances[neighbor] {
                    distances[neighbor] = new_distance;
                    previous_nodes[neighbor] = Some(current_node);
                }
            }
        }
    }

    let shortest_path = reconstruct_path(previous_nodes, source_node_id, destination_node_id);
    let total_weight = distances[destination_node_id];

    (shortest_path, total_weight)
}

fn find_min_distance_node(distances: &[usize], visited: &[bool]) -> usize {
    let mut min_distance = usize::MAX;
    let mut min_index = 0;

    for (index, (&distance, &is_visited)) in distances.iter().zip(visited).enumerate() {
        if !is_visited && distance < min_distance {
            min_distance = distance;
            min_index = index;
        }
    }

    min_index
}

fn reconstruct_path(
    previous_nodes: Vec<Option<usize>>,
    source_node_id: usize,
    destination_node_id: usize,
) -> Vec<usize> {
    let mut path = vec![];
    let mut current_node = destination_node_id;

    while current_node != source_node_id {
        path.push(current_node);
        current_node = previous_nodes[current_node].unwrap();
    }

    path.push(source_node_id);
    path.reverse();

    path
}
```

프로그램을 실행하려면 `dijkstra.rs`로 저장하고 `rustc dijkstra.rs`를 사용하여 컴파일합니다. 그런 다음 입력 파일 경로와 소스 및 대상 노드 ID를 사용하여 컴파일된 바이너리를 실행할 수 있습니다:

```sh
$ ./dijkstra input.txt 0 4
Shortest path: [0, 2, 3, 4]
Total weight: 9
```

입력 파일에는 그래프의 인접 행렬이 포함되어야 하며, 각 행은 공백으로 구분된 가중치 목록입니다. 예를 들어, 다음 입력 파일은 5개의 노드(0~4)와 그 사이에 가중치가 적용된 가장자리가 있는 그래프를 나타냅니다:

```
0 10 1 0 0
10 0 0 5 1
1 0 0 2 0
0 5 2 0 2
0 1 0 2 0
```