Задания
Версия для печати и копирования в MS Word
Тип 23 № 92565
i

В тек­сто­вом файле со­дер­жит­ся опи­са­ние ацик­ли­че­ско­го ори­ен­ти­ро­ван­но­го взве­шен­но­го графа.

За­да­ние 23

В каж­дой стро­ке файла за­пи­са­ны два на­ту­раль­ных числа (L, M) и одно по­ло­жи­тель­ное ве­ще­ствен­ное число (W). L и M  — но­ме­ра вер­шин графа, W  — вес ребра, ве­ду­ще­го из вер­ши­ны L в вер­ши­ну M. Таким об­ра­зом, ко­ли­че­ство строк в файле равно ко­ли­че­ству рёбер в графе. Две вер­ши­ны графа не могут быть со­еди­не­ны более чем одним реб­ром.

Най­ди­те и за­пи­ши­те в от­ве­те целую часть длины крат­чай­ше­го пути из вер­ши­ны с но­ме­ром 1 в вер­ши­ну с но­ме­ром 100. Су­ще­ство­ва­ние хотя бы од­но­го та­ко­го пути га­ран­ти­ру­ет­ся. Под дли­ной крат­чай­ше­го пути по­ни­ма­ет­ся ми­ни­маль­ная сумма весов рёбер, со­став­ля­ю­щих путь.

Для вы­пол­не­ния этого за­да­ния сле­ду­ет на­пи­сать про­грам­му.

Вер­ши­ны графа могут быть про­ну­ме­ро­ва­ны не под­ряд. L ≤ 1000, M ≤ 1000; W ≤ 10 000. Ко­ли­че­ство строк в файле не пре­вос­хо­дит 200. Числа в стро­ках раз­де­ле­ны про­из­воль­ным не­ну­ле­вым ко­ли­че­ством про­бе­лов и/или та­бу­ля­ций.

Ти­по­вой при­мер ор­га­ни­за­ции дан­ных во вход­ном файле для графа на ри­сун­ке

100  12       1.0

6          7          7.0

6          1          1.0

1          7          5.5

7          100 2.0

4          100 8.0

1          100 12.0

1          4          2.5

 

Для при­ведённого при­ме­ра вер­ным от­ве­том будет 7.

Ти­по­вой при­мер имеет ил­лю­стра­тив­ный ха­рак­тер. Для вы­пол­не­ния за­да­ния ис­поль­зуй­те дан­ные из при­ла­га­е­мо­го файла.

Спрятать решение

Ре­ше­ние.

Граф всех воз­мож­ных путей (жёлтым цве­том вы­де­лен нуж­ный путь, про­хо­дя­щий через нуж­ные вер­ши­ны):

 

При­ведём ре­ше­ние на языке Python.

from functools import lru_cache

import sys

 

# Уве­ли­чим лимит ре­кур­сии на слу­чай боль­шо­го ко­ли­че­ства вер­шин

sys.setrecursionlimit(10000)

 

# 1. Счи­ты­ва­ем дан­ные и стро­им спи­сок смеж­но­сти графа

graph = {}

 

# За­ме­ни­те '23.txt' на имя ва­ше­го файла с дан­ны­ми

with open('demo_23.txt') as f:

for line in f:

if line.strip():

# Раз­де­ля­ем стро­ку по про­бе­лам/та­бу­ля­ци­ям

parts = line.split()

u, v, w = int(parts[0]), int(parts[1]), float(parts[2])

if u not in graph:

graph[u] = []

graph[u].append((v, w))

 

# 2. Ре­кур­сив­ная функ­ция для по­ис­ка крат­чай­ше­го пути

@lru_cache(None)

def get_min_path(start, end):

if start == end:

return 0

if start not in graph:

return 0

min_dist = float('inf')

for neighbor, weight in graph[start]:

dist = weight + get_min_path(neighbor, end)

if dist < min_dist:

min_dist = dist

return min_dist

 

# 3. Вы­чис­ля­ем ответ

result = get_min_path(1, 100)

print("Целая часть длины крат­чай­ше­го пути:", int(result))

 

 

Ответ: 10971.