Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
ProblemDla danego grafu nieskierowanego należy znaleźć jego graf krawędziowy |
Graf krawędziowy (ang. line graph) powstaje z grafu w sposób następujący:
Oto graf wyjściowy | Wszystkie
krawędzie zastępujemy wierzchołkami |
Wierzchołki
łączymy ze sobą wtedy, gdy w grafie wyjściowym ich krawędzie łączyły się poprzez wspólny wierzchołek. |
Otrzymujemy graf krawędziowy. |
Uogólniając, graf krawędziowy GE powstaje z grafu G w ten sposób, że krawędzie grafu G stają się wierzchołkami w grafie krawędziowym GE. Dwa wierzchołki (v1, v2) i (v3, v4) grafu krawędziowego GE łączą się krawędzią, jeśli:
Poniższy algorytm działa poprawnie zarówno dla grafu skierowanego jak i dla nieskierowanego. W pierwszym przypadku graf krawędziowy będzie skierowany, w drugim nieskierowany. Musimy jedynie pamiętać, aby w grafie nieskierowanym nadać krawędzi odwrotnej ten sam numer porządkowy.
n | : | liczba wierzchołków w grafie G, n C. |
m | : | liczba krawędzi w grafie G, m C. |
G | : | graf zadany w dowolnie wybrany sposób, algorytm tego nie precyzuje. |
GE | : | graf krawędziowy grafu G. |
v, u, w | : | numery wierzchołków w grafie, v, u, w C. |
iv-u, iu-w | : | numery krawędzi w grafie G, iv-u, iu-w C. |
K01: | Utwórz zerowy graf GE o m wierzchołkach |
graf zawiera m wierzchołków, nie zawiera krawędzi |
K02: | Dla v = 0, 1, …,
n-1, wykonuj kroki K03…K08 |
przechodzimy przez kolejne wierzchołki grafu G |
K03: | Dla każdego
sąsiada u wierzchołka v : wykonuj kroki K04…K08 |
przeglądamy wszystkich sąsiadów wierzchołka v |
K04: | iv-u ← numer krawędzi v – u | mamy krawędź v-u, które jest wchodząca w wierzchołku u |
K05: |
Dla każdego sąsiada w wierzchołka u
: wykonuj kroki K06…K08 |
przeglądamy wszystkich sąsiadów wierzchołka u |
K06: |
Jeśli w = v, to następny obieg pętli K05 |
pomijamy wierzchołek startowy |
K07: | iu-w ← numer krawędzi u – w | mamy krawędź u-w, która jest wychodząca w wierzchołku u |
K08: |
Dodaj krawędź (iv-u, iu-w) do grafu GE |
w GE krawędź wchodzącą łączymy z krawędzią wychodzącą |
K09: | Zakończ z wynikiem GE |
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. |
Program wyznacza graf krawędziowy
(w postaci tablicy list sąsiedztwa) dla danego grafu
nieskierowanego. 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. Definicja składa się z trzech liczb u v i. Dwie pierwsze liczby definiują numery wierzchołków, pomiędzy którymi jest krawędź. Trzecia liczba oznacza numer tej krawędzi. Na wyjściu program wyświetla zawartość tablicy list sąsiedztwa dla grafu krawędziowego. |
Dane przykładowe (przekopiuj do
schowka i wklej do okna konsoli):
|
Pascal// Graf krawędziowy // Data : 22.04.2014 // (C)2014 mgr Jerzy Wałaszek //--------------------------- program line_graph; // Definicja elementu listy sąsiedztwa type PSLel = ^SLel; SLel = record next : PSLel; // Następny element listy v : integer; // Wierzchołek docelowy i : integer; // Numer krawędzi end; var n, m : integer; // Liczba wierzchołków, liczba krawędzi G, GE : array of PSLel; // Grafy i, u, v, ei : integer; p, r, s : PSLel; begin read (n, m); // Czytamy rozmiary grafu SetLength (G, n); // Tworzymy zerowy graf G for i := 0 to n-1 do G [i] := nil; SetLength (GE, m); // Tworzymy zerowy graf GE for i := 0 to m-1 do GE [i] := nil; // Odczytujemy definicje krawędzi grafu G for i := 1 to m do begin read (v, u, ei); // Czytamy wierzchołki i numer krawędzi new (p); // Tworzymy rekord listy p^.v := u; // Wypełniamy go danymi p^.i := ei; p^.next := G [v]; // Rekord dołączamy do listy sąsiedztwa wierzchołka v G [v] := p; new (p); // To samo dla krawędzi odwrotnej p^.v := v; p^.i := ei; p^.next := G [u]; G [u] := p; end; // Tworzymy graf krawędziowy for v := 0 to n-1 do // Przechodzimy przez kolejne wierzchołki grafu begin p := G [v]; // Przechodzimy przez listę sąsiadów wierzchołka v while p <> nil do begin r := G [p^.v]; // Przechodzimy przez listę sąsiadów sąsiada v while r <> nil do begin if r^.v <> v then begin new (s); // Tworzymy nowy element listy s^.v := r^.i; // Wierzchołkiem docelowym będzie krawędź wychodząca s^.next := GE [p^.i]; // Wierzchołkiem startowym będzie krawędź wchodząca GE [p^.i] := s; // Dodajemy krawędź do grafu krawędziowego end; r := r^.next; // Następny sąsiad end; p := p^.next; // Następny sąsiad end; end; // Wyświetlamy wyniki writeln; for i := 0 to m-1 do begin write (i, ': '); p := GE [i]; while p <> nil do begin write (p^.v, ' '); p := p^.next; end; writeln; end; // Usuwamy dynamiczne struktury for i := 0 to n-1 do begin p := G [i]; while p <> nil do begin r := p; p := p^.next; dispose (r); end; end; SetLength (G, 0); for i := 0 to m-1 do begin p := GE [i]; while p <> nil do begin r := p; p := p^.next; dispose (r); end; end; SetLength (GE, 0); end. |
// Graf krawędziowy // Data : 22.04.2014 // (C)2014 mgr Jerzy Wałaszek //--------------------------- #include <iostream> using namespace std; // Definicja elementu listy sąsiedztwa struct SLel { SLel * next; // Następny element listy; int v; // Wierzchołek docelowy int i; // Numer krawędzi }; int main() { int n, m; // Liczba wierzchołków, liczba krawędzi SLel **G, **GE; // Grafy int i, u, v, ei; SLel *p, *r, *s; cin >> n >> m; // Czytamy rozmiary grafu G = new SLel * [n]; // Tworzymy zerowy graf G for(i = 0; i < n; i++) G [i] = NULL; GE = new SLel * [m]; // Tworzymy zerowy graf GE for(i = 0; i < m; i++) GE [i] = NULL; // Odczytujemy definicje krawędzi grafu G for(i = 0; i < m; i++) { cin >> v >> u >> ei; // Czytamy wierzchołki i numer krawędzi p = new SLel; // Tworzymy rekord listy p->v = u; // Wypełniamy go danymi p->i = ei; p->next = G [v]; // Element dołączamy do listy sąsiedztwa wierzchołka v G [v] = p; p = new SLel; // To samo dla krawędzi odwrotnej p->v = v; p->i = ei; p->next = G [u]; G [u] = p; } // Tworzymy graf krawędziowy for(v = 0; v < n; v++) // Przechodzimy przez kolejne wierzchołki grafu for(p = G [v]; p; p = p->next) // Przechodzimy przez listę sąsiadów wierzchołka v for(r = G [p->v]; r; r = r->next) // Przechodzimy przez listę sąsiadów sąsiada v if(r->v != v) { s = new SLel; // Tworzymy nowy element listy s->v = r->i; // Wierzchołkiem docelowym będzie krawędź wychodząca s->next = GE [p->i]; // Wierzchołkiem startowym będzie krawędź wchodząca GE [p->i] = s; // Dodajemy krawędź do grafu krawędziowego } // Wyświetlamy wyniki cout << endl; for(i = 0; i < m; i++) { cout << i << ": "; for(p = GE [i];p;p = p->next) cout << p->v << " "; cout << endl; } // Usuwamy dynamiczne struktury for(i = 0; i < n; i++) { p = G [i]; while(p) { r = p; p = p->next; delete r; } } delete [] G; for(i = 0; i < m; i++) { p = GE [i]; while(p) { r = p; p = p->next; delete r; } } delete [] GE; return 0;} |
Basic' Graf krawędziowy ' Data : 22.04.2014 ' (C)2014 mgr Jerzy Wałaszek '--------------------------- ' Definicja elementu listy sąsiedztwa Type SLel Dim Next As SLel Ptr ' Następny element listy Dim v As Integer ' Wierzchołek docelowy Dim i As Integer ' Numer krawędzi End Type Dim As Integer n, m ' Liczba wierzchołków, liczba krawędzi Dim As SLel Ptr Ptr G, GE ' Grafy Dim As Integer i, u, v, ei Dim As SLel Ptr p, r, s Open Cons For Input As #1 Input #1, n, m ' Czytamy rozmiary grafu G = New SLel Ptr [n] ' Tworzymy zerowy graf G For i = 0 To n-1 G [i] = 0 Next GE = New SLel Ptr [m] ' Tworzymy zerowy graf GE For i = 0 To m-1 GE [i] = 0 Next ' Odczytujemy definicje krawędzi grafu G For i = 1 To m Input #1, v, u, ei ' Czytamy wierzchołki i numer krawędzi p = New SLel ' Tworzymy element listy p->v = u ' Wypełniamy go danymi p->i = ei p->next = G [v] ' Element dołączamy do listy sąsiedztwa wierzchołka v G [v] = p p = New SLel ' To samo dla krawędzi odwrotnej p->v = v p->i = ei p->next = G [u] G [u] = p Next Close #1 ' Tworzymy graf krawędziowy For v = 0 To n-1 ' Przechodzimy przez kolejne wierzchołki grafu p = G [v] ' Przechodzimy przez listę sąsiadów wierzchołka v While p r = G [p->v] ' Przechodzimy przez listę sąsiadów sąsiada v While r If r->v <> v Then s = New SLel ' Tworzymy nowy element listy s->v = r->i ' Wierzchołkiem docelowym będzie krawędź wychodząca s->next = GE [p->i] ' Wierzchołkiem startowym będzie krawędź wchodząca GE [p->i] = s ' Dodajemy krawędź do grafu krawędziowego End If r = r->Next ' Następny sąsiad Wend p = p->Next ' Następny sąsiad Wend Next ' Wyświetlamy wyniki Print For i = 0 To m-1 Print Using "&:";i; p = GE [i] While p Print p->v; p = p->Next Wend Print Next ' Usuwamy dynamiczne struktury For i = 0 To n-1 p = G [i] While p r = p p = p->Next Delete r Wend Next Delete [] G For i = 0 To m-1 p = GE [i] While p r = p p = p->Next Delete r Wend Next Delete [] GE End |
Wynik: | |
6 9 0 1 0 0 2 1 0 3 2 1 4 3 2 3 4 2 5 6 3 4 5 3 5 7 4 5 8 0: 1 2 3 1: 0 2 4 6 2: 0 1 4 5 7 3: 0 5 8 4: 1 6 2 5 7 5: 2 4 7 3 8 6: 1 4 7 8 7: 2 4 5 6 8 8: 3 5 6 7 |
→ |
Przerób powyższy program, tak aby wyznaczał graf krawędziowy dla grafu skierowanego (sam algorytm pozostaje bez zmian!).
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 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:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.