| 
					
				 | 
			
			
				@@ -0,0 +1,110 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::collections::BTreeMap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use std::ops::Add; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Граф - дерево деревьев 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+type Graph<V, E> = BTreeMap<V, BTreeMap<V, E>>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+pub fn dijkstra<V: Ord + Copy, E: Ord + Copy + Add<Output = E>>( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    graph: &Graph<V, E>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    start: V, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+) -> BTreeMap<V, Option<(V, E)>> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut res = BTreeMap::new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut queue = BTreeMap::new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Путь от начала до начала равен 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res.insert(start, None); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (new, weight) in &graph[&start] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Сохраняем путь 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        res.insert(*new, Some((start, *weight))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Сохраняем в очередь 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        queue.insert(*new, *weight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Проходим по всем элементам очереди 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    while let Some((vertex, path_weight)) = queue.pop_first() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Проходим по всем следующим связанным элементам 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for (next, weight) in &graph[&vertex] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Считаем итоговую сумму на данный момент 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let new_weight = path_weight + *weight; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Ищем следующий элемент в матрице 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            match res.get(next) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Если следующий элемент есть в матрице и имеет расстояние, меньшее найденного на этой итерации - не делаем ничего 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Some(Some((_, weight_next))) if new_weight >= *weight_next => {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Если следующий элемент начальный - не делаем ничего 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                Some(None) => {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Если следующего элемента нет - сохраняем в матрицу и очередь с новым весом 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                _ => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    res.insert(*next, Some((vertex, new_weight))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    queue.insert(*next, new_weight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    res 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn insert_edge<V: Ord + Copy, E: Ord + Copy>(graph: &mut Graph<V, E>, v1: V, v2: V, c: E) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Добавляем А->Б 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    graph.entry(v1).or_default().insert(v2, c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Добавляем Б-А 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    graph.entry(v2).or_default().insert(v1, c); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+fn main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let args: Vec<String> = std::env::args().skip(1).collect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Если аргументы пусты или -h/--help 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if args.is_empty() || args[0] == "--help" || args[0] == "-h" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        println!("Usage: {} <start> <edges>.", std::env::args().nth(0).unwrap_or("dijkstra".to_string())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        println!("Each vertex is specified as a single latin character"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        println!("Edges are separated by a whitespace and formatted as A-B=C where A, B are vertex names and C is the length of the edge"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Стартовая вершина - первый аргумент 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let start = args[0].chars().nth(0).expect("No start specified"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Парсим аргументы в список рёбер 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let edges: Vec<(char, char, u128)> = args 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .iter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .skip(1) // Пропускаем первый аргумент - стартовую вершину 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .map(|s| { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Разбиваем аргумент по символам - и = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let parts: Vec<&str> = s.split(&['-', '='][..]).collect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                parts[0].chars().next().unwrap(), // Первая вершина 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                parts[1].chars().next().unwrap(), // Вторая вершина 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                parts[2].parse().unwrap(),        // Длина 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        .collect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Создаем граф 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let mut graph = Graph::new(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Для каждого найденного ребра из вершины добавляем в граф 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for edge in &edges { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        insert_edge(&mut graph, edge.0.clone(), edge.1.clone(), edge.2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    println!( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        "Total edges: {}\nStarting vertex: {}\nFinding paths...", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        edges.len(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        start 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Считаем длины путей 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    let paths = dijkstra(&graph, start); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // Выводим длину для каждого пути 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for path in &paths { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        let to = path.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if let Some(second) = path.1 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            println!("Length of path from {} to {} is {}", start, to, second.1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            println!("Length of path from {} to {} is 0", start, to); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |