0484 - Lant Minim

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ă lista muchiilor unui graf neorientat și două vârfuri p q . Să se determine cel mai scurt lanț cu extremitățile p q.

Date de intrare

Fişierul de intrare lantminimIN.txt conţine pe prima linie numerele n p q, reprezentând numărul de vârfuri ale grafului și cele două vârfuri date. Fiecare dintre următoarele linii conține câte o pereche de numere i j, cu semnificația că există muchie între i și j.

Date de ieşire

Fişierul de ieşire lantminimOUT.txt va conţine pe prima linie numărul de vârfuri din lanțul determinat. A doua linie va conține vârfurile din acest lanț, separate prin exact un spațiu.

Restricţii şi precizări

  • 1 ≤ n ≤ 100
  • 1 ≤ i , j ≤ n
  • în fișierul de intrare muchiile se pot repeta;
  • orice lanț de lungime minimă cu extremitățile p q este acceptat;
  • pentru toate datele de test există cel puțin un lanț de la p la q;

Exemplul 1

lantminimIN.txt

6 2 6
1 2
1 3
1 4
3 4
4 5
4 6
5 6

lantminimOUT.txt

4
2 1 4 6 

Exemplul 2

lantminimIN.txt

101 101 101

lantminimOUT.txt

Datele nu corespund restrictiilor impuse

Rezolvare

import heapq

def dijkstra(graf, start, end):
    # Inițializare distanțe și coadă de priorități
    distante = {varf: float('infinity') for varf in graf}
    distante[start] = 0
    coada_prioritati = [(0, start)]

    while coada_prioritati:
        distanta_curenta, varf_curent = heapq.heappop(coada_prioritati)

        # Verificare dacă am găsit un drum mai scurt
        if distanta_curenta > distante[varf_curent]:
            continue

        for vecin, pondere in graf[varf_curent]:
            distanta = distanta_curenta + pondere

            # Actualizare distanțe și adăugare în coadă
            if distanta < distante[vecin]:
                distante[vecin] = distanta
                heapq.heappush(coada_prioritati, (distanta, vecin))

    # Construire lanț minim
    drum_minim = []
    varf_curent = end
    while varf_curent != start:
        drum_minim.insert(0, varf_curent)
        varf_curent = graf[varf_curent][0][0]  # Se folosește primul vecin în loc de [1]

    drum_minim.insert(0, start)
    return drum_minim

def verifica_restrictii(n, muchii, p, q):
    # Verificare restricții
    if not (1 <= n <= 100 and all(1 <= i <= n and 1 <= j <= n for i, j in muchii)):
        return False

    # Alte verificări specifice, dacă este cazul

    return True

# Citire date din fișierul de intrare
with open("lantminimIN.txt", "r") as fisier:
    n, p, q = map(int, fisier.readline().split())
    muchii = [tuple(map(int, linie.split())) for linie in fisier.readlines()]

# Verificare restricții
if not verifica_restrictii(n, muchii, p, q):
    with open("lantminimOUT.txt", "w") as fisier:
        fisier.write("Datele nu corespund restrictiilor impuse")
else:
    # Construire graf
    graf = {i: [] for i in range(1, n + 1)}
    for muchie in muchii:
        graf[muchie[0]].append((muchie[1], 1))
        graf[muchie[1]].append((muchie[0], 1))

    # Aplicare algoritm Dijkstra
    drum_minim = dijkstra(graf, p, q)

    # Scriere rezultat în fișierul de ieșire
    with open("lantminimOUT.txt", "w") as fisier:
        fisier.write(str(len(drum_minim)) + "\n")
        fisier.write(" ".join(map(str, drum_minim)))