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

©2026 mgr Jerzy Wałaszek

Grafy dwudzielne

SPIS TREŚCI

Problem

Należy zbadać, czy dany graf nieskierowany i spójny jest grafem dwudzielnym.

Rozwiązanie

Graf dwudzielny (ang. bipartite graph lub bigraph) jest grafem, którego wierzchołki możemy podzielić na dwa rozłączne zbiory U i V. Wierzchołki należące do zbioru U mogą się łączyć krawędziami tylko z wierzchołkami ze zbioru V i na odwrót.

obrazek

Innymi słowy, każda krawędź grafu dwudzielnego łączy wierzchołki z różnych zbiorów.

Wierzchołki należące do zbioru U możemy traktować jako pokolorowane np. na niebiesko, a wierzchołki należące do zbioru V jako pokolorowane np. na  czerwono. Graf będzie grafem dwudzielnym, jeśli uda nam się pokolorować wszystkie jego wierzchołki, tak aby żaden z sąsiadów danego wierzchołka nie był tego samego koloru co sam wierzchołek.

Do kolorowania grafu możemy wykorzystać algorytm przejścia wszerz BFS lub algorytm przejścia w głąb DFS. Zasada jest następująca:

Początkowo wszystkie wierzchołki grafu powinny posiadać kolor neutralny. Wybieramy dowolny wierzchołek w grafie i kolorujemy go np. na czerwono. Następnie przechodzimy algorytmem DFS lub BFS przez graf począwszy od wybranego wierzchołka kolorując po drodze wszystkich nie odwiedzonych sąsiadów na kolor przeciwny (czerwony → niebieski, niebieski → czerwony) do koloru odwiedzanego wierzchołka. Jeśli któryś z odwiedzonych wierzchołków sąsiadujących posiada taki sam kolor jak wierzchołek odwiedzany, to graf nie jest grafem dwudzielnym: dana krawędź łączy wierzchołki tej samej klasy.

Prześledźmy te operacje na przykładowym grafie:

obrazek Mamy przykładowy graf, dla którego chcemy
sprawdzić dwudzielność (ang. bipartiteness).
Początkowo wszystkie wierzchołki posiadają
kolor neutralny – tutaj szary.
obrazek W grafie wybieramy dowolny wierzchołek
(u nas niech to dla prostoty będzie
wierzchołek 0)
i kolorujemy go np. na czerwono.
Wybrany wierzchołek posłuży jako punkt
startowy dla przejścia BFS (lub alternatywnie
DFS
)
.
obrazek Sprawdzamy, czy każdy sąsiad posiada inny
kolor od wierzchołka startowego (jeśli nie, to
graf nie jest dwudzielny i operację sprawdzania
dwudzielności możemy natychmiast zakończyć
z wynikiem negatywnym)
, a następnie kolorujemy
go na kolor przeciwny do koloru wierzchołka
startowego – tutaj na niebiesko.
obrazek Operację sprawdzania i kolorowania powtarzamy
dla każdego sąsiada zgodnie z wybranym
algorytmem przejścia grafu – tutaj BFS.
obrazek I dalej…
obrazek I dalej…
obrazek Koniec, graf jest dwudzielny.

Algorytm sprawdzania dwudzielności grafu za pomocą BFS

Wejście:

n : liczba wierzchołków w grafie; n ∈ C.
graf : zadany w dowolnie wybrany sposób, algorytm tego nie precyzuje.

Wyjście:

true – graf jest dwudzielny.
false – graf nie jest dwudzielny.

Elementy pomocnicze:

Q : kolejka.
i, v, u : wierzchołki; i,v,u ∈ C.
n elementowa tablica zawierająca kolory wierzchołków, w przypadku grafu dwudzielnego kolory posiadają następujące kody:
0 - szary, 1- czerwony, (-1) - niebieski.

Lista kroków:

K01: Utwórz n elementową tablicę C
K02: Ustaw wszystkie elementy tablicy C na 0 ; 0 oznacza kolor szary
K03: Utwórz pustą kolejkę Q
K04: Dla i = 0, 1, …, n-1, ; przechodzimy przez kolejne wierzchołki grafu
     wykonuj kroki K05…K15
K05:   Jeśli C[i] ≠ 0, ; szukamy wierzchołka szarego, który będzie
       to następny obieg pętli K04 ; wierzchołkiem startowym
K06:   C[i] ← 1 ; wierzchołek startowy kolorujemy na czerwono
K07:   Q.push(i) ; numer wierzchołka umieszczamy w kolejce
K08:   Dopóki Q.empty() = false, ; rozpoczynamy przejście BFS
       wykonuj kroki K09…K15
K09:     vQ.front() ; pobieramy element z początku kolejki
K10:     Q.pop() ; pobrany element usuwamy z kolejki
K11:     Dla każdego sąsiada u wierzchołka v: ; przetwarzamy
         wykonuj kroki K12…K15 ; sąsiadów wierzchołka v
K12:       Jeśli C[u] = C[v], ; sąsiad ma ten sam kolor, więc graf
           to zakończ z wynikiem false ; nie może być dwudzielny
K13:       Jeśli C[u] ≠ 0, to ; szukamy wierzchołka niepokolorowanego,
           następny obieg pętli K11 ; czyli jeszcze nieodwiedzonego
K14:       C[u] = -C[v] ; kolorujemy sąsiada na kolor przeciwny
K15:       Q.push(u) ; sąsiada umieszczamy w kolejce
K16: Zakończ z wynikiem true

Algorytm z przejściem DFS jest identyczny z powyższym. Jedyna zmiana polega na zastąpieniu kolejki Q stosem S.

Algorytm po niewielkiej przeróbce pozwala również wyznaczyć oba zbiory U i V. Odpowiednia informacja zawarta jest w tablicy C.

Z postaci przedstawionego powyżej algorytmu wynika, że najlepszym sposobem reprezentowania w nim grafu jest tablica list sąsiedztwa.


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.

Program odczytuje definicję grafu nieskierowanego, tworzy tablicę list sąsiedztwa, a następnie sprawdza, czy graf jest dwudzielny. Jeśli tak, to wypisuje 'BIPARTITE GRAPH'. W przeciwnym razie wypisuje 'NOT A BIPARTITE GRAPH'. Za wierzchołek startowy przyjmowany jest wierzchołek nr 0.
Dane przykładowe (przekopiuj do schowka i wklej do okna konsoli):
obrazek
Graf dwudzielny
  17 23
0 2
0 3
1 2
1 14
2 6
3 4
3 6
3 13
4 7
4 12
5 6
5 9
5 10
6 7
6 8
6 12
7 13
8 9
10 11
10 14
10 15
11 16
12 16
obrazek
Graf niedwudzielny
  17 24
0 2
0 3
1 2
1 14
2 6
3 4
3 6
3 13
4 7
4 12
5 6
5 9
5 10
6 7
6 8
6 12
7 13
8 9
10 11
10 14
10 15
11 16
12 16
13 16
Pascal
// Dwudzielność grafu
// Data: 24.11.2013
// (C)2013 mgr Jerzy Wałaszek
//---------------------------

program test_bigraph;

// Typy dla dynamicznej tablicy
// list sąsiedztwa i kolejki
type
  PSLel = ^SLel;
  SLel =  record
    next : PSLel;
    v : integer;
  end;

  TList = array of PSLel;

// Definicja typu obiektowego queue
//---------------------------------
  queue = object
    private
      head : PSLel;
      tail : PSLel;

    public
      constructor init;
      destructor destroy;
      function empty : boolean;
      function front : integer;
      procedure push(v : integer);
      procedure pop;
  end;

//---------------------
// Metody obiektu queue
//---------------------

// Konstruktor-tworzy pustą listę
//-------------------------------
constructor queue.init;
begin
  head := nil;
  tail := nil;
end;

// Destruktor-usuwa listę z pamięci
//---------------------------------
destructor queue.destroy;
begin
  while not empty do pop;
end;

// Sprawdza, czy kolejka jest pusta
//---------------------------------
function queue.empty : boolean;
begin
  if head = nil then
    empty := true
  else
    empty := false;
end;

// Zwraca początek kolejki.
// Wartość specjalna to -MAXINT
//-----------------------------
function queue.front : integer;
begin
  if head = nil then
    front := -MAXINT
  else
    front := head^.v;
end;

// Zapisuje do kolejki
//--------------------
procedure queue.push(v : integer);
var
  p : PSLel;
begin
  new(p);
  p^.next := nil;
  p^.v := v;
  if tail = nil then head := p
  else tail^.next := p;
  tail := p;
end;

// Usuwa z kolejki
//----------------
procedure queue.pop;
var
  p : PSLel;
begin
  if head <> nil then
  begin
    p := head;
    head := head^.next;
    if head = nil then tail := nil;
    dispose(p);
  end;
end;

// Funkcja testuje dwudzielność grafu
// n - liczba wierzchołków grafu
// A - tablica list sąsiedztwa
//-----------------------------------
function isBipartite(n : integer;
                 var A : TList)
                       : boolean;
var
  Q : queue;
  C : array of integer;
  v, u, i : integer;
  p : PSLel;

begin
  // Tworzymy tablicę kolorów
  SetLength(C, n);
  for i := 0 to n-1 do
    C[i] := 0;
  // Tworzymy pustą kolejkę
  Q.init;
  // Przechodzimy przez
  // kolejne wierzchołki
  for i := 0 to n-1 do
    // Szukamy wierzchołka szarego
    if C[i] = 0 then
    begin
      // Wierzchołek startowy
      // kolorujemy na czerwono
      C[i] := 1;
      // i umieszczamy w kolejce
      Q.push(i);
      // Przejście BFS
      while Q.empty = false do
      begin
        // Pobieramy wierzchołek
        // z kolejki
        v := Q.front;
        // Pobrany wierzchołek
        // usuwamy z kolejki
        Q.pop;
        // Przeglądamy sąsiadów
        // wierzchołka v
        p := A[v];
        while p <> nil do
        begin
          // pobieramy z listy
          // sąsiedztwa numer
          // sąsiada
          u := p^.v;
          if C[u] = C[v] then
          begin
            SetLength(C, 0);
            Q.destroy;
            // Sąsiad ma ten
            // sam kolor
            Exit(false);
          end;
          // Jeśli wierzchołek
          // nie jest odwiedzony,
          if C[u] = 0 then
          begin
            // kolorujemy go na
            // kolor przeciwny
            C[u] := -C[v];
            // i umieszczamy
            // w kolejce
            Q.push(u);
          end;
          // Następny sąsiad
          p := p^.next;
        end;
      end;
    end;
  SetLength(C, 0);
  isBipartite := true;
end;

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

var
  n, m, i, v1, v2 : integer;
  p, r : PSLel;
  A : TList;

begin
  // Czytamy liczbę
  // wierzchołków i krawędzi
  read(n, m);
  // Tworzymy tablicę
  // list sąsiedztwa
  SetLength(A, n);
  // Tablice wypełniamy
  // pustymi listami
  for i := 0 to n-1 do
    A[i] := nil;
  // Odczytujemy kolejne
  // definicje krawędzi
  for i := 0 to m-1 do
  begin
    // Wierzchołek startowy
    // i końcowy krawędzi
    read(v1, v2);
    // Tworzymy nowy element
    new(p);
    // Numerujemy go jako v2
    p^.v := v2;
    // Dodajemy go na początek
    // listy A[v1]
    p^.next := A[v1];
    A[v1] := p;
    // Krawędź w drugą stronę,
    // bo graf jest nieskierowany
    new(p);
    p^.v := v1;
    p^.next := A[v2];
    A[v2] := p;
  end;
  if isBipartite(n, A) then
    writeln('BIPARTITE GRAPH')
  else
    writeln('NOT A BIPARTITE GRAPH');
  // Usuwamy tablicę
  // list sąsiedztwa
  for i := 0 to n-1 do
  begin
    p := A[i];
    while p <> nil do
    begin
      r := p;
      p := p^.next;
      dispose(r);
    end;
  end;
  SetLength(A, 0);
end.
C++
// Dwudzielność grafu
// Data: 24.11.2013
// (C)2013 mgr Jerzy Wałaszek
//---------------------------

#include <iostream>

using namespace std;

const int MAXINT = 2147483647;

// Typy dla dynamicznej
// tablicy list sąsiedztwa
// i kolejki
struct SLel
{
  SLel * next;
  int v;
};

// Typ obiektowy queue
//--------------------
class queue
{
  private:
    SLel * head;
    SLel * tail;

  public:
    queue(); // konstruktor
    ~queue(); // destruktor
    bool empty(void);
    int  front(void);
    void push(int v);
    void pop(void);
};

//---------------------
// Metody obiektu queue
//---------------------

// Konstruktor
//------------
queue::queue()
{
  head = tail = nullptr;
}

// Destruktor
//-----------
queue::~queue()
{
  while(head) pop();
}

// Sprawdza, czy kolejka jest pusta
//---------------------------------
bool queue::empty(void)
{
  return !head;
}

// Zwraca początek kolejki.
// Wartość specjalna to -MAXINT
//-----------------------------
int queue::front (void)
{
  if(head)
    return head->v;
  else
    return -MAXINT;
}

// Zapisuje do kolejki
//--------------------
void queue::push(int v)
{
  SLel * p = new SLel;
  p->next = nullptr;
  p->v = v;
  if(tail)
    tail->next = p;
  else
    head = p;
  tail = p;
}

// Usuwa z kolejki
//----------------
void queue::pop(void)
{
  if(head)
  {
    SLel * p = head;
    head = head->next;
    if(!head)
      tail = nullptr;
    delete p;
  }
}

// Funkcja testuje dwudzielność
// grafu
// n - liczba wierzchołków grafu
// A - tablica list sąsiedztwa
//------------------------------
bool isBipartite(int n,
                 SLel ** A)
{
  queue Q;
  int * C;
  int v, u, i;
  SLel * p;

  // Tworzymy tablicę kolorów
  C = new int[n];
  for(i = 0; i < n; i++)
    C[i] = 0;

  // Przechodzimy przez
  // kolejne wierzchołki
  for(i = 0; i < n; i++)
    // Szukamy wierzchołka
    // szarego
    if(!C[i])
    {
      // Wierzchołek startowy
      // kolorujemy na czerwono
      C[i] = 1;
      // i umieszczamy w kolejce
      Q.push(i);
      // Przejście BFS
      while(!Q.empty())
      {
        // Pobieramy wierzchołek
        // z kolejki
        v = Q.front();
        // Pobrany wierzchołek
        // usuwamy z kolejki
        Q.pop();
        // Przeglądamy sąsiadów
        // wierzchołka v
        for(p = A[v]; p; p = p->next)
        {
          // pobieramy z listy
          // sąsiedztwa numer sąsiada
          u = p->v;
          if(C[u] == C[v])
          {
            delete [] C;
            // Sąsiad ma ten sam kolor
            return false;
          }

          // Jeśli wierzchołek
          // nie jest odwiedzony,
          if(!C[u])
          {
            // kolorujemy go
            // na kolor przeciwny
            C[u] = -C[v];
            // i umieszczamy w kolejce
            Q.push(u);
          }
        }
      }
    }
  delete [] C;
  return true;
}

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

int main()
{
  int n, m, i, v1, v2;
  SLel * p, * r, ** A;

  // Czytamy liczbę
  // wierzchołków
  // i krawędzi
  cin >> n >> m;
  // Tworzymy tablicę
  // list sąsiedztwa
  A = new SLel * [n];
  // Tablicę wypełniamy
  // pustymi listami
  for(i = 0; i < n; i++)
    A[i] = nullptr;
  // Odczytujemy kolejne
  // definicje krawędzi
  for(i = 0; i < m; i++)
  {
    // Wierzchołek startowy
    // i końcowy krawędzi
    cin >> v1 >> v2;
    // Tworzymy nowy element
    p = new SLel;
    // Numerujemy go jako v2
    p->v = v2;
    // Dodajemy go
    // na początek
    // listy A[v1]
    p->next = A[v1];
    A[v1] = p;
    // Krawędź w drugą stronę,
    // bo graf jest nieskierowany
    p = new SLel;
    p->v = v1;
    p->next = A[v2];
    A[v2] = p;
  }
  if(isBipartite(n, A))
    cout << "BIPARTITE GRAPH";
  else
    cout << "NOT A BIPARTITE GRAPH";
  cout << endl;
  // Usuwamy tablicę
  // list sąsiedztwa
  for(i = 0; i < n; i++)
  {
    p = A[i];
    while(p)
    {
      r = p;
      p = p->next;
      delete r;
    }
  }
  delete [] A;
  return 0;
}
Basic
' Testowanie dwudzielności grafu
' Data: 24.11.2013
' (C)2013 mgr Jerzy Wałaszek
'-------------------------------

Const MAXINT = 2147483647

' Typy dla dynamicznej tablicy
' list sąsiedztwa i kolejki
Type SLel
  next As SLel Ptr
  v As Integer
End Type

' Definicja typu obiektowego queue
'---------------------------------
Type queue
  Private:
    head As SLel Ptr
    tail As SLel Ptr

  Public:
    Declare Constructor
    Declare Destructor
    Declare Function empty As Integer
    Declare Function front As Integer
    Declare Sub push(ByVal v As Integer)
    Declare Sub pop
End Type

'---------------------
' Metody obiektu queue
'---------------------

' Konstruktor
'------------
Constructor queue
  head = 0
  tail = 0
End Constructor

' Destruktor
'-----------
Destructor queue
  While empty = 0
    pop
  Wend
End Destructor

' Sprawdza, czy kolejka jest pusta
'---------------------------------
Function queue.empty As Integer
  If head = 0 Then Return 1
  Return 0
End Function

' Zwraca początek kolejki.
' Wartość specjalna to -MAXINT
'-----------------------------
Function queue.front As Integer
  If head = 0 then
    front = -MAXINT
  Else
    front = head->v
  End If
End Function

' Zapisuje do kolejki
'--------------------
Sub queue.push(ByVal v As Integer)
  Dim p As SLel Ptr
  p = new SLel
  p->next = 0
  p->v = v
  If tail = 0 Then
    head = p
  Else
    tail->next = p
  End If
  tail = p
End Sub

' Usuwa z kolejki
'----------------
Sub queue.pop
  Dim p As SLel Ptr
  If head Then
    p = head
    head = head->next
    If head = 0 Then tail = 0
    Delete p
  End If
End Sub

' Funkcja testuje dwudzielność grafu
' n - liczba wierzchołków grafu
' A - tablica list sąsiedztwa
'-----------------------------------
Function isBipartite(ByVal n As integer, _
                 ByVal A As SLel Ptr Ptr) _
                         As Integer
  Dim As queue Q
  Dim As Integer Ptr C
  Dim As Integer v, u, i
  Dim As SLel Ptr p

  ' Tworzymy tablicę kolorów
  C = New Integer [n]
  For i = 0 To n-1
    C[i] = 0
  Next
  ' Przechodzimy przez kolejne wierzchołki
  For i = 0 To n-1
    ' Szukamy wierzchołka szarego
    If C[i] = 0 Then
      ' Wierzchołek startowy
      ' kolorujemy na czerwono
      C[i] = 1
      ' i umieszczamy w kolejce
      Q.push(i)
      ' Przejście BFS
      While Q.empty = 0
        ' Pobieramy wierzchołek z kolejki
        v = Q.front
        ' Pobrany wierzchołek
        ' usuwamy z kolejki
        Q.pop
        p = A[v]
        ' Przeglądamy sąsiadów wierzchołka v
        While p <> 0
          ' pobieramy z listy sąsiedztwa
          ' numer sąsiada
          u = p->v
          If C[u] = C[v] Then
            Delete [] C
            ' Sąsiad ma ten sam kolor
            Return 0
          End If
          ' Jeśli wierzchołek nie
          ' jest odwiedzony, 
          If C[u] = 0 Then
            ' kolorujemy go
            ' na kolor przeciwny
            C[u] = -C[v]
            ' i umieszczamy w kolejce
            Q.push(u)
          End If
          ' Następny wierzchołek
          p = p->next
        Wend
      Wend
    End If
  Next
  Delete [] C
  Return 1
End Function

' **********************
' *** PROGRAM GŁÓWNY ***
' **********************

Dim As Integer n, m, i, v1, v2
Dim As SLel Ptr p, r
Dim As SLel Ptr Ptr A

Open Cons For Input As #1
' Czytamy liczbę wierzchołków i krawędzi
Input #1, n, m
' Tworzymy tablicę list sąsiedztwa
A = new SLel Ptr [n]
' Tablicę wypełniamy pustymi listami
For i = 0 To n-1
  A[i] = 0
Next
' Odczytujemy kolejne definicje krawędzi
For i = 0 To m -1
  ' Wierzchołek startowy i końcowy krawędzi
  Input #1, v1, v2
  ' Tworzymy nowy element
  p = new SLel
  ' Numerujemy go jako v2
  p->v = v2
  ' Dodajemy go na początek listy A[v1]
  p->next = A[v1]
  A[v1] = p
  ' Krawędź w drugą stronę,
  ' bo graf jest nieskierowany
  p = new SLel
  p->v = v1
  p->next = A[v2]
  A[v2] = p
Next
Close #1
If isBipartite(n, A) Then
  Print "BIPARTITE GRAPH"
Else
  Print "NOT A BIPARTITE GRAPH"
EndIf
' Usuwamy tablicę list sąsiedztwa
For i = 0 To n-1
  p = A[i]
  While p
    r = p
    p = p->next
    Delete r
  Wend
Next
Delete [] A
End
Python (dodatek)
# Testowanie dwudzielności grafu
# Data: 21.01.2025
# (C)2025 mgr Jerzy Wałaszek
#-------------------------------

MAXINT = 2147483647

# Klasa dla dynamicznej tablicy
# list sąsiedztwa i kolejki
class SLel:
    def __init__(self):
        self.next = None
        self.v = 0


# Klasa Queue
#------------
class Queue:
    # Konstruktor
    def __init__(self):
        self.head = None
        self.tail = None


    # Destruktor
    def __del__(self):
        while self.head:
            self.pop()


    # Sprawdza, czy kolejka jest pusta
    def empty(self):
        return not self.head


    # Zwraca początek kolejki.
    # Wartość specjalna to -MAXINT
    def front(self):
        global MAXINT
        if not self.head:
            return -MAXINT
        else:
            return self.head.v


    # Zapisuje do kolejki
    def push(self, v):
        p = SLel()
        p.next = None
        p.v = v
        if not self.tail:
            self.head = p
        else:
            self.tail.next = p
        self.tail = p


    # Usuwa z kolejki
    def pop(self):
        if self.head:
            self.head = self.head.next
            if not self.head:
                self.tail = None


# Funkcja testuje dwudzielność grafu
# n - liczba wierzchołków grafu
# a - tablica list sąsiedztwa
def is_bipartite(n, a):
    q = Queue()
    # Tworzymy tablicę kolorów
    c = [0] * n
    # Przechodzimy przez
    # kolejne wierzchołki
    for i in range(n):
        # Szukamy wierzchołka szarego
        if c[i] == 0:
            # Wierzchołek startowy
            # kolorujemy na czerwono
            c[i] = 1
            # i umieszczamy w kolejce
            q.push(i)
            # Przejście BFS
            while not q.empty():
                # Pobieramy wierzchołek
                # z kolejki
                v = q.front()
                # Pobrany wierzchołek
                # usuwamy z kolejki
                q.pop()
                p = a[v]
                # Przeglądamy sąsiadów
                # wierzchołka v
                while p:
                    # pobieramy z listy
                    # sąsiedztwa
                    # numer sąsiada
                    u = p.v
                    if c[u] == c[v]:
                        del c
                        # Sąsiad ma ten
                        # sam kolor
                        return False
                    # Jeśli wierzchołek
                    # nie jest odwiedzony, 
                    if not c[u]:
                        # kolorujemy go
                        # na kolor
                        # przeciwny
                        c[u] = -c[v]
                        # i umieszczamy
                        # w kolejce
                        q.push(u)
                    # Następny wierzchołek
                    p = p.next
    del c
    return True

# **********************
# *** PROGRAM GŁÓWNY ***
# **********************

# Czytamy liczbę wierzchołków i krawędzi
x = input().split()
n = int(x[0])
m = int(x[1])
# Tworzymy tablicę list sąsiedztwa
a = [None] * n
# Odczytujemy kolejne definicje krawędzi
for i in range(m):
    # Wierzchołek startowy
    # i końcowy krawędzi
    x = input().split()
    v1 = int(x[0])
    v2 = int(x[1])
    # Tworzymy nowy element
    p = SLel()
    # Numerujemy go jako v2
    p.v = v2
    # Dodajemy go na początek listy a[v1]
    p.next = a[v1]
    a[v1] = p
    # Krawędź w drugą stronę,
    # bo graf jest nieskierowany
    p = SLel()
    p.v = v1
    p.next = a[v2]
    a[v2] = p
if is_bipartite(n, a):
    print("BIPARTITE GRAPH")
else:
    print("NOT A BIPARTITE GRAPH")
# Usuwamy tablicę list sąsiedztwa
for i in range(n):
    while a[i]:
        a[i] = a[i].next
del a
Wyniki:
17 23
0 2
0 3
1 2
1 14
2 6
3 4
3 6
3 13
4 7
4 12
5 6
5 9
5 10
6 7
6 8
6 12
7 13
8 9
10 11
10 14
10 15
11 16
12 16
BIPARTITE GRAPH
  17 24
0 2
0 3
1 2
1 14
2 6
3 4
3 6
3 13
4 7
4 12
5 6
5 9
5 10
6 7
6 8
6 12
7 13
8 9
10 11
10 14
10 15
11 16
12 16
13 16
NOT A BIPARTITE GRAPH

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
©2026 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.