Nadesłany przez Tomasz Lubiński, 09 sierpnia 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
cykl_eulera/graf.pas:
//Tomasz Lubiński (c)2001
//www.algorytm.org
//generowanie grafu o zadanym nasyceniu
//poszukiwanie cyklu Euler'a w podanym grafie
unit graf;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
wsk_kolejki=^kolejka;
kolejka = record
element: SmallInt;
wskaznik: wsk_kolejki;
end;
wagi = record
p : SmallInt;
d : SmallInt;
waga: SmallInt;
end;
TForm1 = class(TForm)
Button3: TButton;
Label3: TLabel;
GroupBox1: TGroupBox;
Label1: TLabel;
Label2: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Button1: TButton;
ListBox1: TListBox;
CheckBox1: TCheckBox;
procedure GenerujClick(Sender: TObject);
procedure A1(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
poczatek, koniec, gora: wsk_kolejki;
Macierz: Array of Array of SmallInt;
lk: Array of wagi;
n, licznik: Integer;
cykl, spojnosc: Boolean;
implementation
{$R *.DFM}
//generowanie grafu - macierz dolnotrójkątna
procedure TForm1.GenerujClick(Sender: TObject);
var b,i,j,wierzcholek : Integer;
begin
Finalize(Macierz);
n:=StrToInt(edit1.text);
b:=StrToInt(edit2.text);
SetLength(Macierz, n+1);
for i:=0 to n do
SetLength(Macierz[i], i); //tworzenie macierz dolnotrójkątna dynamicznej
randomize;
for i:=2 to n do
for j:=1 to i-1 do
if random(100)<b then Macierz[i,j]:=random(1000); //ustawienie stopnia nasycenia
if CheckBox1.Checked=True Then
begin
for wierzcholek:=1 to n-1 do //parzystosc wierzcholkow
begin
i:=0;
for j:=1 to wierzcholek-1 do
if macierz[wierzcholek, j]>0 then i:=i+1;
for j:=wierzcholek+1 to n do
if macierz[j, wierzcholek]>0 then i:=i+1;
if (i mod 2) <> 0 then
begin
i:=Random(n-wierzcholek)+wierzcholek+1;
if macierz[i, wierzcholek]>0 then macierz[i, wierzcholek]:=0 else
macierz[i, wierzcholek]:=random(1000);
end;
end;
end;
end;
procedure DoKolejki(var koniec: wsk_kolejki; element:Integer);
var poprzedni: wsk_kolejki;
begin
licznik:=licznik+1;
if poczatek<>nil then
begin
poprzedni:=koniec;
New(koniec);
poprzedni^.wskaznik:=koniec;
koniec^.element:=element;
koniec^.wskaznik:=nil;
end
else
begin
New(koniec);
koniec^.element:=element;
koniec^.wskaznik:=nil;
poczatek:=koniec;
end;
end;
procedure ZKolejki(var poczatek: wsk_kolejki; var element:Integer);
var nastepny: wsk_kolejki;
begin
if poczatek<>nil then
begin
element:=poczatek^.element;
nastepny:=poczatek^.wskaznik;
Dispose(poczatek);
poczatek:=nastepny;
if poczatek=nil then koniec:=nil;
end;
end;
procedure W_Szerz; //przegladanie grafu wszerz
var a, wierzcholek: Integer;
begin
DoKolejki(koniec, 1);
macierz[1,0]:=1;
repeat
ZKolejki(poczatek, wierzcholek);
for a:=1 to wierzcholek-1 do
if (macierz[wierzcholek, a]>0) and (macierz[a,0]=0) then
begin
DoKolejki(koniec, a);
macierz[a,0]:=1;
end;
for a:=wierzcholek+1 to n do
if (macierz[a, wierzcholek]>0) and (macierz[a,0]=0) then
begin
DoKolejki(koniec, a);
macierz[a,0]:=1;
end;
until poczatek=nil;
if licznik<>n then spojnosc:=false else spojnosc:=true;
end;
procedure ZeStosu(var gora: wsk_kolejki; var element: Integer);
var poprzedni: wsk_kolejki;
begin
if gora<>nil then
begin
element:=gora^.element;
poprzedni:=gora^.wskaznik;
Dispose(gora);
gora:=poprzedni;
end;
end;
procedure NaStos(var gora: wsk_kolejki; var element: Integer);
var poprzedni: wsk_kolejki;
begin
poprzedni:=gora;
New(gora);
gora^.element:=element;
gora^.wskaznik:=poprzedni;
end;
procedure Cykl_Eulera;
var a,wierzcholek,i: Integer;
label tutaj;
begin
W_Szerz;
if spojnosc=false then exit; //jezeli nie jest spójny to nie ma cyklu
cykl:=false;
for wierzcholek:=1 to n do //zbadanie parzystosci wierzcholkow
begin
i:=0;
for a:=1 to wierzcholek-1 do
if macierz[wierzcholek, a]>0 then i:=i+1;
for a:=wierzcholek+1 to n do
if macierz[a, wierzcholek]>0 then i:=i+1;
if (i mod 2) <> 0 then exit;
end;
cykl:=true;
wierzcholek:=1;
NaStos(gora, wierzcholek);
while gora<>nil do //szukanie cyklu tak dlugo jak jes jakis wierzcholek na stosie
begin
tutaj:
wierzcholek:=gora^.element;
for a:=1 to wierzcholek-1 do
if macierz[wierzcholek, a]>0 then
begin
macierz[wierzcholek, a]:=-macierz[wierzcholek, a];
NaStos(gora,a); //wrzucanie wierzcholka na stos
goto tutaj
end;
for a:=wierzcholek+1 to n do
if macierz[a, wierzcholek]>0 then
begin
macierz[a, wierzcholek]:=-macierz[a, wierzcholek];
NaStos(gora,a); //wrzucanie wierzcholka na stos
goto tutaj
end;
ZeStosu(gora, wierzcholek); //zdejmowanie ze stosu gdy nie ma gdzie pojsc
Form1.ListBox1.Items.Add(IntToStr(wierzcholek));
end;
end;
procedure TForm1.A1(Sender: TObject);
var i,wierzcholek: Integer;
begin
ListBox1.Items.Clear;
Cykl_Eulera;
if cykl=false then ListBox1.Items.Add('Brak Cyklu') else ListBox1.Items.Add('Cykl:');
if spojnosc=false then ListBox1.Items.Add('Graf nie jest spojny') else ListBox1.Items.Add('Graf jest spojny');
for i:=1 to n do macierz[i,0]:=0; //wyzerowanie odwiedzin wierzcholka
licznik:=0;
for wierzcholek:=1 to n do //wyzerowanie odwiedzin krawedzi
begin
for i:=1 to wierzcholek-1 do
if macierz[wierzcholek, i]<0 then macierz[wierzcholek, i]:=-macierz[wierzcholek, i];
for i:=wierzcholek+1 to n do
if macierz[i, wierzcholek]<0 then macierz[i, wierzcholek]:=-macierz[i, wierzcholek];
end;
end;
end.

