0588 - Dijkstra

De la Universitas MediaWiki
Versiunea pentru tipărire nu mai este suportată și poate avea erori de randare. Vă rugăm să vă actualizați bookmarkurile browserului și să folosiți funcția implicită de tipărire a browserului.

Cerința

Se dă un graf orientat ponderat cu n noduri – în care fiecare arc are asociat un cost, număr natural strict pozitiv, și un nod p. Să se determine, folosind algoritmul lui Dijkstra, costul minim al drumului de la p la fiecare nod al grafului.

Date de intrare

Fișierul de intrare dijkstraIN.txt conține pe prima linie numerele n p, iar următoarele linii câte un triplet i j c, cu semnificația: există arcul (i j) și are costul c.

Date de ieșire

Fișierul de ieșire dijkstraOUT.txt va conține pe prima linie n numere, separate prin exact un spațiu, al i-lea număr reprezentând costul drumului minim de la p la i. Dacă nu există drum de la p la un anumit vârf, costul afișat va fi -1.În cazul în care restricțiile nu sunt îndeplinite, se va afișa mesajul "Nu corespunde restricțiilor impuse".

Restricții și precizări

  • 1 ≤ n ≤ 100
  • costul unui arc va fi mai mic decât 1000
  • costul unui drum este egal cu suma costurilor arcelor care îl compun

Exemplul 1:

dijkstraIN.txt

5 4
1 3 1
2 1 2
4 2 1
4 3 8
5 3 5
5 4 2

dijkstraOUT.txt

3 1 4 0 -1

Exemplul 2:

dijkstraIN.txt

1001 12
1 3 1
2 1 2
4 2 1
4 3 8
5 3 5
5 4 2

dijkstraOUT.txt

"Datele nu corespund restrictiilor impuse"

Rezolvare

import heapq

def dijkstra(graph, start):
    n = len(graph)
    INF = float('inf')
    distante = [INF] * n
    distante[start] = 0
    heap = [(0, start)]

    while heap:
        dist_curenta, nod_curent = heapq.heappop(heap)

        if dist_curenta > distante[nod_curent]:
            continue

        for vecin, cost in graph[nod_curent]:
            distanta_noua = dist_curenta + cost
            if distanta_noua < distante[vecin]:
                distante[vecin] = distanta_noua
                heapq.heappush(heap, (distanta_noua, vecin))

    return distante

def verificare_restrictii(n, graph):
    # Verificarea restrictiilor
    if not (1 <= n <= 100):
        return False
    for node_edges in graph:
        for _, cost in node_edges:
            if not (cost < 1000):
                return False
    return True

def citeste_intrare(file_path):
    with open(file_path, 'r') as file:
        n, p = map(int, file.readline().split())
        
        # Verificare restrictii
        if not (1 <= n <= 100):
            return n, p, None

        graf = [[] for _ in range(n)]

        for _ in range(n):
            i, j, c = map(int, file.readline().split())
            graf[i-1].append((j-1, c))

    return n, p, graf

def scrie_iesire(file_path, distante, restrictii_valide):
    with open(file_path, 'w') as file:
        if not restrictii_valide:
            file.write("Datele nu corespund restrictiilor impuse")
        else:
            for dist in distante:
                if dist == float('inf'):
                    file.write("-1 ")
                else:
                    file.write(str(dist) + " ")

def main():
    fisier_intrare = 'dijkstraIN.txt'
    fisier_iesire = 'dijkstraOUT.txt'

    n, p, graf = citeste_intrare(fisier_intrare)

    # Verificare restricții
    restrictii_valide = verificare_restrictii(n, graf)

    if not restrictii_valide:
        # Dacă restricțiile nu sunt respectate, scrie mesajul în fișierul de ieșire
        scrie_iesire(fisier_iesire, [], restrictii_valide)
    else:
        # Altfel, aplică algoritmul lui Dijkstra și scrie rezultatele în fișierul de ieșire
        distante = dijkstra(graf, p-1)
        scrie_iesire(fisier_iesire, distante, restrictii_valide)

if __name__ == "__main__":
    main()