Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

Autor artykułu: mgr Jerzy Wałaszek

©2025 mgr Jerzy Wałaszek
I LO w Tarnowie

Problem komiwojażera

SPIS TREŚCI

Problem

W danym grafie należy znaleźć ścieżkę o najmniejszej sumie wag krawędzi, która przechodzi dokładnie jeden raz przez każdy wierzchołek i wraca do wierzchołka startowego.

Rozwiązanie

Wyobraźmy sobie komiwojażera, który podróżuje od miasta do miasta, sprzedając swoje produkty lub zawierając różne oferty handlowe. Wyrusza z miasta rodzinnego, po czym jego trasa przebiega dokładnie jeden raz przez każde z miast. Na koniec komiwojażer powraca do swojego miasta rodzinnego. Z  oczywistych powodów chce, aby trasa podróży była najkrótszą ze wszystkich możliwych tras. W ten sposób powstaje problem wędrującego komiwojażera (ang. TSP – Travelling Salesman Problem).

W terminologii grafów miasta są wierzchołkami grafu, a trasy pomiędzy nimi to krawędzie z wagami. Waga krawędzi może odpowiadać odległości pomiędzy miastami połączonymi tą krawędzią, czasowi podróży lub kosztom przejazdu – zależy, co chcemy w podróżny komiwojażera zminimalizować. Trasa komiwojażera jest cyklem przechodzącym przez każdy wierzchołek grafu dokładnie jeden raz – jest to zatem cykl Hamiltona.

Znalezienie właściwego cyklu Hamiltona jest zadaniem bardzo trudnym obliczeniowo. Wyobraźmy sobie graf zupełny (ang. complete graph – graf, w którym każdy wierzchołek jest połączony z każdym) o 10 wierzchołkach.

obrazek

Ile różnych cykli Hamiltona zawiera taki graf? Otóż pierwszą krawędź cyklu można wybrać na 9 różnych sposobów, ponieważ każdy wierzchołek grafu jest połączony krawędzią z pozostałymi dziewięcioma. Po wyborze pierwszej krawędzi pozostaje nam 8 możliwych wyborów, później 7, 6,  5, …, 1. W efekcie otrzymujemy liczbę cykli Hamiltona równą:

LH = 9×8×7×6×5×4×3×2×1 = 9! = 362880

Dla n wierzchołków:

LH = (n-1)×(n-2)×…3×2×1 = (n-1)!

Wynik jest bardzo niekorzystny, ponieważ prowadzi do wykładniczej klasy złożoności obliczeniowej O(n!). Dla każdego znalezionego cyklu Hamiltona liczymy sumę wag krawędzi i zapamiętujemy cykl o najmniejszej sumie wag. Na przykład w naszym grafie może to być następujący cykl (nie sugeruj się długością krawędzi na rysunku – ważne są wagi, a nie długość kreski – czasami miasta mało odległe w linii prostej mogą być połączone długą trasą ze względu na warunki terenowe: góry, jeziora, bagna itp.):

obrazek

Grafy odwzorowujące rzeczywiste sieci połączeń zwykle nie są zupełne – ekonomicznie nieuzasadnione byłoby budowanie osobnych dróg pomiędzy każdą parą miast. Zwykle drogi przebiegają od jednego miasta do drugiego, a w niektórych się rozchodzą. Dlatego opisany powyżej przypadek jest przypadkiem pesymistycznym. Jednakże problem dalej posiada wykładniczą klasę złożoności obliczeniowej. Rozważmy dla przykładu graf posiadający 100 wierzchołków. Załóżmy, iż każdy wierzchołek łączy się z czterema innymi wierzchołkami grafu. Zatem ich stopień wynosi 4. W pesymistycznym przypadku ilość cykli Hamiltona do przebadania może wynosić:

Z pierwszego wierzchołka możemy pójść na 4 różne sposoby, z drugiego na 3, z trzeciego na 3, …, i z 99 na trzy. Otrzymujemy zatem:

LH = 4×399 ≈ 3100 ≈ 5, 15×1047

Zatem dla grafu posiadającego n wierzchołków o stopniu s otrzymamy

LH ≈ (s-1)n

Czyli liczba cykli lub ścieżek do przebadania rośnie wykładniczo. Nawet na szybkim komputerze wyznaczenie rozwiązania może przekroczyć stulecia. Problemy algorytmiczne o złożoności wykładniczej są traktowane jako nierozwiązywalne dla dużych n.

Istnieją algorytmy znajdujące przybliżone rozwiązania problemu wędrującego komiwojażera w czasie wielomianowym, lecz są one bardzo zaawansowane i trudne w implementacji. Jeśli liczba wierzchołków w grafie nie jest duża (np. do 20) i graf nie jest grafem zupełnym (złożoność O(n!)), to rozwiązanie problemu komiwojażera możemy uzyskać prostym algorytmem, który wyznacza wszystkie cykle Hamiltona, liczy sumę wag krawędzi i zwraca cykl o najmniejszej sumie wag. Rozwiązanie to jest o tyle dobre, iż zawsze zwróci cykl optymalny, a nie przybliżony. Również jest łatwe do zrozumienia i implementacji. Podstawowa wada to wykładnicza złożoność obliczeniowa, która uniemożliwia analizę większych grafów.

Algorytm rozwiązujący problem komiwojażera dla małych grafów

Rekurencyjna procedura TSP(n,graf,v,v0,d,dH,S,SH,vs)

Wejście:

n : liczba wierzchołków w grafie; n ∈ C.
graf : zadany w dowolnie wybrany sposób, algorytm tego nie precyzuje. Definicja grafu powinna udostępniać wagi krawędzi.
v : wierzchołek bieżący; v ∈ C.
v0 : wierzchołek startowy; v0 ∈ C.
d : suma wag krawędzi cyklu Hamiltona; d ∈ C.
dH : pomocnicza suma wag krawędzi; dH ∈ C.
S : stos wierzchołków.
SH : pomocniczy stos wierzchołków.
vs : n elementowa logiczna tablica odwiedzin.

Wyjście:

S : stos zawierający numery kolejnych wierzchołków cyklu Hamiltona o najmniejszej sumie wag krawędzi lub stos pusty w przypadku braku cyklu Hamiltona w grafie.
d : suma wag krawędzi cyklu Hamiltona.

Elementy pomocnicze:

u : wierzchołek; u ∈ C.

Lista kroków:

K01: SH.push(v) ; Odwiedzony wierzchołek dopisujemy do ścieżki
K02: Jeśli SH nie zawiera n wierzchołków, ; Jeśli brak ścieżki Hamiltona,
     to idź do kroku K10 ; przechodzimy do wyszukiwania
K03: Jeśli nie istnieje krawędź z v do v0, ; Jeśli ścieżka Hamiltona nie jest cyklem,
     to idź do kroku K17 ; odrzucamy ją
K04: dH ← dH + waga krawędzi z v do v0 ; Uwzględniamy w sumie wagę ostatniej krawędzi cyklu
K05: Jeśli dHd, ; Jeśli znaleziony cykl jest gorszy od bieżącego,
     to idź do kroku K08 ; odrzucamy go
K06: d ← dH ; Zapamiętujemy sumę wag cyklu
K07: Skopiuj stos SH do stosu S ; oraz sam cykl Hamiltona
K08: dH ← dH - waga krawędzi z v do v0 ; Usuwamy wagę ostatniej krawędzi z sumy
K09: Idź do kroku K17
K10: vs[v] ← true ; Wierzchołek zaznaczamy jako odwiedzony,
     ; aby nie był ponownie wybierany przez DFS
K11: Dla każdego sąsiada u wierzchołka v: ; Przechodzimy przez listę sąsiedztwa
     wykonuj kroki K12…K15
K12:   Jeśli vs[u] = true, ; Omijamy wierzchołki odwiedzone
       to następny obieg pętli K11
K13:   dHdH + waga krawędzi z v do u ; Obliczamy nową sumę wag krawędzi ścieżki
K14:   TSP(n,graf,u,v0,d,dH,S,SH,vs) ; Wywołujemy rekurencyjnie poszukiwanie cyklu
K15:   dHdH - waga krawędzi z v do u ; Usuwamy wagę krawędzi z sumy
K16: vs[v] ← false ; Zwalniamy bieżący wierzchołek
K17: SH.pop() ; Usuwamy bieżący wierzchołek ze ścieżki
K18: Zakończ

Lista kroków algorytmu głównego

K01: Utwórz i wyzeruj vs, S i SH
K02: d ← ∞; dH ← 0 ; Początkową sumę ustawiamy jako największą z możliwych
K03: TSP(n,graf,u,v0,d,dH,S,SH,vs) ; Wyszukiwanie cyklu Hamiltona rozpoczynamy
     ; od wierzchołka startowego
K04: Jeśli S.empty() = false, ; Sprawdzamy, czy algorytm znalazł cykl Hamiltona.
     to pisz S oraz d ; Jeśli tak, to wypisujemy go.
     inaczej pisz "NO HAMILTONIAN CYCLE"
K05: Zakończ

Uwaga: większość parametrów wejściowych może być zrealizowana jako zmienne globalne, co znacznie uprości wywołania rekurencyjne.


Przykładowe programy

Uwaga:

Zanim uruchomisz program, przeczytaj wstęp do tego artykułu, w którym wyjaśniamy funkcje tych programów oraz sposób korzystania z nich.

Poniższy program jest przykładową realizacją algorytmu rozwiązywania problemu komiwojażera. Z uwagi na wykładniczą klasę złożoności obliczeniowej program potrafi w rozsądnym czasie znaleźć rozwiązanie tylko dla grafów o niewielkiej liczbie węzłów (powiedzmy, do 20). Definicja danych wejściowych jest następująca:

W pierwszym wierszu program odczytuje kolejno liczbę wierzchołków n oraz liczbę krawędzi m. W m kolejnych wierszach znajdują się definicje krawędzi. Każda definicja składa się z trzech liczb x y w. Pierwsza i druga liczba określa wierzchołki grafu, które są ze sobą połączone tą krawędzią. Trzecia liczba jest wagą w krawędzi.

Jako wierzchołek startowy program przyjmuje wierzchołek o numerze 0.

Na wyjściu zostaje wypisany cykl Hamiltona o najmniejszej sumie wag krawędzi oraz wartość tej sumy. Jeśli graf nie zawiera cyklu Hamiltona, to pojawi się napis:

NO HAMILTONIAN CYCLE.
Dane przykładowe (przekopiuj do schowka i wklej do okna konsoli):
obrazek 8 16
0 1 2
0 2 2
0 3 4
0 4 3
1 2 2
1 5 1
1 6 1
2 4 2
2 5 1
3 5 2
3 7 3
4 6 4
4 7 5
5 6 2
5 7 2
6 7 2
Pascal
// Problem komiwojażera
// Data: 22.03.2014
// (C)2014 mgr Jerzy Wałaszek
//---------------------------

program TSProblem;

// Typy dla dynamicznej
// macierzy sąsiedztwa
type
  // Wiersz tablicy sąsiedztwa
  nptr = array of boolean;
  // Wiersz macierzy wag krawędzi
  wnptr = array of integer;

// Zmienne globalne
var
  n,m,v0,d,dh,sptr,shptr : integer;
  // Macierz sąsiedztwa
  A : array of nptr;
  // Macierz wag
  W : array of wnptr;
  // Stosy w tablicy
  S, Sh : array of integer;
  // Tablica odwiedzin
  vs : array of boolean;

// Rekurencyjna procedura
// poszukiwania cyklu Hamiltona
// o najmniejszej sumie wag krawędzi
// v - wierzchołek bieżący
//----------------------------------
procedure TSP(v : integer);
var
  u : integer;
begin
  // zapamiętujemy na stosie
  // bieżący wierzchołek
  Sh[shptr] := v;
  inc(shptr);
  // jeśli brak ścieżki Hamiltona,
  // to jej szukamy
  if shptr < n then
  begin
    // Oznaczamy bieżący wierzchołek
    // jako odwiedzony
    vs[v] := true;
    // Przeglądamy sąsiadów
    // wierzchołka v
    for u := 0 to n-1 do
      // Szukamy nieodwiedzonego
      // jeszcze sąsiada
      if A[v][u] and not vs[u] then
      begin
        // Dodajemy wagę krawędzi
        // v - u do sumy
        inc(dh, W[v][u]);
        // Rekurencyjnie wywołujemy
        // szukanie cyklu Hamiltona
        TSP(u);
        // Usuwamy wagę krawędzi
        // z sumy
        dec(dh, W[v][u]);
      end;
    // Zwalniamy bieżący wierzchołek
    vs[v] := false;
  end
  // Jeśli znaleziona ścieżka
  // jest cyklem Hamiltona,
  else if A[v0][v] then
  begin
    // to sprawdzamy,
    // czy ma najmniejszą sumę wag
    inc(dh, W[v][v0]);
    // Jeśli tak,
    if dh < d then
    begin
      // To zapamiętujemy tę sumę
      d := dh;
      // oraz kopiujemy stos Sh do S
      for u := 0 to shptr-1 do
        S[u] := Sh[u];
      sptr := shptr;
    end;
    // Usuwamy wagę krawędzi
    // v - v0 z sumy
    dec(dh, W[v][v0]);
  end;
  // Usuwamy bieżący
  // wierzchołek ze ścieżki
  dec(shptr);
end;

//**********************
//*** Program główny ***
//**********************

var
  i, j, x, y, z : integer;
begin
  // Czytamy liczbę
  // wierzchołków i krawędzi
  read(n, m);
  // Tworzymy struktury
  // dynamiczne i inicjujemy je
  SetLength(S, n);
  SetLength(Sh, n);
  SetLength(vs, n);
  SetLength(A, n);
  SetLength(W, n);
  for i := 0 to n-1 do
  begin
    SetLength(A[i], n);
    SetLength(W[i], n);
    for j := 0 to n-1 do
    begin
      A[i][j] := false;
      W[i][j] := 0;
    end;
    vs[i] := false;
  end;
  sptr := 0;
  shptr := 0;
  // Odczytujemy dane wejściowe
  for i := 0 to m-1 do
  begin
    read(x, y, z);
    // Krawędź x - y
    A[x][y] := true;
    A[y][x] := true;
    // Waga krawędzi x - y
    W[x][y] := z;
    W[y][x] := z;
  end;
  writeln;
  // Rozpoczynamy algorytm
  d  := MAXINT;
  dh := 0;
  v0 := 0;
  TSP(v0);
  if sptr > 0 then
  begin
    for i := 0 to sptr-1 do
      write(S[i], ' ');
    writeln(v0);
    writeln('d = ', d);
  end
  else
    writeln('NO HAMILTONIAN CYCLE');
  writeln;
  // Usuwamy tablice dynamiczne
  SetLength(S, 0);
  SetLength(Sh, 0);
  SetLength(vs, 0);
  for i := 0 to n-1 do
  begin
    SetLength(A[i], 0);
    SetLength(W[i], 0);
  end;
  SetLength(A, 0);
  SetLength(W, 0);
end.
C++
// Problem komiwojażera
// Data: 22.03.2014
// (C)2014 mgr Jerzy Wałaszek
//---------------------------

#include <iostream>

using namespace std;

const int MAXINT = 2147483647;

// Zmienne globalne
int n,m,v0,d,dh,sptr,shptr;
// Macierz sąsiedztwa
bool **A;
// Macierz wag krawędzi
int **W;
// Stosy w tablicy
int *S, *Sh;
// Tablica odwiedzin
bool *vs;

// Rekurencyjna procedura
// poszukiwania cyklu Hamiltona
// o najmniejszej sumie
// wag krawędzi
// v - wierzchołek bieżący
//-----------------------------
void TSP(int v)
{
  int u;
  // zapamiętujemy na stosie
  // bieżący wierzchołek
  Sh[shptr++] = v;
  // jeśli brak ścieżki
  // Hamiltona, to jej szukamy
  if(shptr < n)
  {
    // Oznaczamy bieżący
    // wierzchołek
    // jako odwiedzony
    vs[v] = true;
    // Przeglądamy sąsiadów
    // wierzchołka v
    for(u = 0; u < n; u++)
      // Szukamy nieodwiedzonego
      // jeszcze sąsiada
      if(A[v][u] && !vs[u])
      {
        // Dodajemy wagę
        // krawędzi v - u do sumy
        dh += W[v][u];
        // Rekurencyjnie
        // wywołujemy szukanie
        // cyklu Hamiltona
        TSP(u);
        // Usuwamy wagę
        // krawędzi z sumy
        dh -= W[v][u];
      }
    // Zwalniamy
    // bieżący wierzchołek
    vs[v] = false;
  }
  // Jeśli znaleziona ścieżka
  // jest cyklem Hamiltona,
  else if(A[v0][v])
  {
    // to sprawdzamy,
    // czy ma najmniejszą
    // sumę wag
    dh += W[v][v0];
    // Jeśli tak,
    if(dh < d)
    {
      // to zapamiętujemy tę sumę
      d = dh;
      // oraz kopiujemy
      // stos Sh do S
      for(u = 0; u < shptr; u++)
        S[u] = Sh[u];
      sptr = shptr;
    }
    // Usuwamy wagę krawędzi
    // v - v0 z sumy
    dh -= W[v][v0];
  }
  // Usuwamy bieżący
  // wierzchołek ze ścieżki
  shptr--;
}

//**********************
//*** Program główny ***
//**********************

int main()
{
  int i, j, x, y, z;

  // Czytamy liczbę
  // wierzchołków i krawędzi
  cin >> n >> m;
  // Tworzymy struktury
  // dynamiczne i inicjujemy je
  S  = new int [n];
  Sh = new int [n];
  vs = new bool [n];
  A  = new bool * [n];
  W  = new int * [n];
  for(i = 0; i < n; i++)
  {
    A[i] = new bool [n];
    W[i] = new int [n];
    for(j = 0; j < n; j++)
    {
      A[i][j] = false;
      W[i][j] = 0;
    }
    vs[i] = false;
  }
  sptr = shptr = 0;

  // Odczytujemy dane wejściowe
  for(i = 0; i < m; i++)
  {
    cin >> x >> y >> z;
    // Krawędź x - y
    A[x][y] = A[y][x] = true;
    // Waga krawędzi x - y
    W[x][y] = W[y][x] = z;
  }
  cout << endl;
  // Rozpoczynamy algorytm
  d  = MAXINT;
  dh = v0 = 0;
  TSP(v0);
  if(sptr)
  {
    for(i = 0; i < sptr; i++)
      cout << S[i] << " ";
    cout << v0 << endl;
    cout << "d = " << d << endl;
  }
  else
    cout << "NO HAMILTONIAN CYCLE"
         << endl;
  cout << endl;
  // Usuwamy tablice dynamiczne
  delete [] S;
  delete [] Sh;
  delete [] vs;
  for(i = 0; i < n; i++)
  {
    delete [] A[i];
    delete [] W[i];
  }
  delete [] A;
  delete [] W;
  return 0;
}
Basic
' Problem komiwojażera
' Data: 22.03.2014
' (C)2014 mgr Jerzy Wałaszek
'---------------------------

Const MAXINT = 2147483647

' Zmienne globalne

Dim Shared As Integer n,m,v0,d
Dim Shared As Integer dhx,sptr,shptr
' Macierz sąsiedztwa
Dim Shared As Byte Ptr Ptr A
' Macierz wag krawędzi
Dim Shared As Integer Ptr Ptr W
' Stosy w tablicy
Dim Shared As Integer Ptr S, Sh
' Tablica odwiedzin
Dim Shared As Byte Ptr vs

' Rekurencyjna procedura
' poszukiwania cyklu Hamiltona
' o najmniejszej sumie wag krawędzi
' v - wierzchołek bieżący
'----------------------------------
Sub TSP (ByVal v As Integer)
  Dim As Integer u

  ' zapamiętujemy na stosie
  ' bieżący wierzchołek
  Sh[shptr] = v
  shptr += 1
  ' jeśli brak ścieżki Hamiltona,
  ' to jej szukamy
  If shptr < n Then
    ' Oznaczamy bieżący
    ' wierzchołek jako odwiedzony
    vs[v] = 1
    ' Przeglądamy sąsiadów
    ' wierzchołka v
    For u = 0 To n-1
      ' Szukamy nieodwiedzonego
      ' jeszcze sąsiada
      If (A[v][u] = 1) AndAlso _
         (vs[u] = 0) Then
        ' Dodajemy wagę
        ' krawędzi v - u do sumy
        dhx += W[v][u]
        ' Rekurencyjnie wywołujemy
        ' szukanie cyklu Hamiltona
        TSP(u)
        ' Usuwamy wagę
        ' krawędzi z sumy
        dhx -= W[v][u]
      End If
    Next
    ' Zwalniamy bieżący wierzchołek
    vs[v] = 0
  ' Jeśli znaleziona ścieżka
  ' jest cyklem Hamiltona,
  ElseIf A[v0][v] = 1 Then
    ' to sprawdzamy,
    ' czy ma najmniejszą sumę wag
    dhx += W[v][v0]
    ' Jeśli tak, 
    If dhx < d Then
      ' To zapamiętujemy tę sumę
      d = dhx
      ' oraz kopiujemy stos Sh do S
      For u = 0 To shptr-1
        S[u] = Sh[u]
      Next
      sptr = shptr
    End If
    ' Usuwamy wagę krawędzi
    ' v - v0 z sumy
    dhx -= W[v][v0]
  End If
  ' Usuwamy bieżący
  ' wierzchołek ze ścieżki
  shptr -= 1
End Sub

'**********************
'*** Program główny ***
'**********************

Dim as Integer i, j, x, y, z

Open Cons For Input As #1
' Czytamy liczbę
' wierzchołków i krawędzi
Input #1, n, m
' Tworzymy struktury
' dynamiczne i inicjujemy je
S  = New Integer [n]
Sh = New Integer [n]
vs = New Byte [n]
A  = New Byte Ptr [n]
W  = New Integer Ptr [n]
For i = 0 To n-1
  A[i] = New Byte [n]
  W[i] = New Integer [n]
  For j = 0 To n-1
    A[i][j] = 0
    W[i][j] = 0
  Next
  vs[i] = 0
Next
sptr  = 0
shptr = 0
' Odczytujemy dane wejściowe
For i = 0 To m-1
  Input #1, x, y, z
  ' Krawędź x-y
  A[x][y] = 1
  A[y][x] = 1
  ' Waga krawędzi x-y
  W[x][y] = z
  W[y][x] = z
Next
Close #1
Print
' Rozpoczynamy algorytm
d  = MAXINT
dhx = 0
v0 = 0
TSP(v0)
If sptr > 0 Then
  For i = 0 To sptr-1
  	 Print S[i];
  Next
  Print v0
  Print " d =";d
Else
  Print "NO HAMILTONIAN CYCLE"
End If
Print
' Usuwamy tablice dynamiczne
Delete [] S
Delete [] Sh
Delete [] vs
For i = 0 To n-1
  Delete [] A[i]
  Delete [] W[i]
Next
Delete [] A
Delete [] W
End
Python (dodatek)
# Problem komiwojażera
# Data: 7.03.2025
# (C)2025 mgr Jerzy Wałaszek
#---------------------------

MAXINT = 2147483647

# Rekurencyjna procedura
# poszukiwania cyklu Hamiltona
# o najmniejszej sumie wag krawędzi
# v - wierzchołek bieżący
#----------------------------------
def tsp(v):
    global s,sh,shptr,sptr,n,m,vs,a,dhx,w,v0,d
    # zapamiętujemy na stosie
    # bieżący wierzchołek
    sh[shptr] = v
    shptr += 1
    # jeśli brak ścieżki Hamiltona,
    # to jej szukamy
    if shptr < n:
        # Oznaczamy bieżący
        # wierzchołek jako odwiedzony
        vs[v] = True
        # Przeglądamy sąsiadów
        # wierzchołka v
        for u in range(n):
            # Szukamy nieodwiedzonego
            # jeszcze sąsiada
            if a[v][u] and not vs[u]:
                # Dodajemy wagę
                # krawędzi v - u do sumy
                dhx += w[v][u]
                # Rekurencyjnie wywołujemy
                # szukanie cyklu Hamiltona
                tsp(u)
                # Usuwamy wagę
                # krawędzi z sumy
                dhx -= w[v][u]
        # Zwalniamy bieżący wierzchołek
        vs[v] = False
    # Jeśli znaleziona ścieżka
    # jest cyklem Hamiltona,
    elif a[v0][v]:
        # to sprawdzamy,
        # czy ma najmniejszą sumę wag
        dhx += w[v][v0]
        # Jeśli tak, 
        if dhx < d:
            # To zapamiętujemy tę sumę
            d = dhx
            # oraz kopiujemy stos Sh do S
            for u in range(shptr):
                s[u] = sh[u]
            sptr = shptr
        # Usuwamy wagę krawędzi
        # v - v0 z sumy
        dhx -= w[v][v0]
    # Usuwamy bieżący
    # wierzchołek ze ścieżki
    shptr -= 1

#**********************
#*** Program główny ***
#**********************

# Czytamy liczbę
# wierzchołków i krawędzi
q = input().split()
n = int(q[0])
m = int(q[1])
# Tworzymy struktury
# dynamiczne i inicjujemy je
s  = [0] * n
sh = [0] * n
vs = [False] * n
a = []
w = []
for i in range(n):
    q = [False] * n
    r = [0] * n
    a.append(q)
    w.append(r)
    del q,r
sptr  = 0
shptr = 0
# Odczytujemy dane wejściowe
for i in range(m):
    q = input().split()
    x = int(q[0])
    y = int(q[1])
    z = int(q[2])
    # Krawędź x-y
    a[x][y] = True
    a[y][x] = True
    # Waga krawędzi x-y
    w[x][y] = z
    w[y][x] = z
print()
# Rozpoczynamy algorytm
d = MAXINT
dhx = 0
v0 = 0
tsp(v0)
if sptr > 0:
    for i in range(sptr):
        print(s[i],end=" ")
    print(v0)
    print(" d =",d)
else:
    print("NO HAMILTONIAN CYCLE")
print()
# Usuwamy tablice dynamiczne
del s,sh,vs
for i in range(n):
    a[i] = None
    w[i] = None
del a,w
Wynik:
 obrazek
8 16
0 1 2
0 2 2
0 3 4
0 4 3
1 2 2
1 5 1
1 6 1
2 4 2
2 5 1
3 5 2
3 7 3
4 6 4
4 7 5
5 6 2
5 7 2
6 7 2

0 1 6 7 3 5 2 4 0
d = 16

do podrozdziału  do strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2025 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.