250 likes | 497 Views
C. B. D. А. E. F. Основні поняття теорії графів. Сукупність точок та ліній, зображена на малюнку і є графом . Точки називаються його вершинами (вузлами), а лінії – ребрами (вітками).
E N D
C B D А E F Основні поняття теорії графів Сукупність точок та ліній, зображена на малюнку і є графом. Точки називаються його вершинами (вузлами), а лінії – ребрами (вітками). Лінія на графі, яка не проходить вздовж жодного його ребра більш ніж один раз, називається ланцюгом. Якщо, рухаючись від однієї вершини, пройти по кількох вершинах графа так, щоб на кожному ребрі побувати лише один раз, а потім знову повернутись у цю ж вершину, такий шлях називається циклом. Т. т. будь-який замкнений ланцюг – цикл. Графи бувають неорієнтованими та орієнтованими, т.т. з напрямленими ребрами. Якщо кожному ребру приписати деяке число(вагу), то граф називається зваженим. Граф називається зв’язним, якщо будь-які дві його вершини зв’язані ланцюгом.
1 3 2 4 Представлення графів Матриця суміжності – це двовимірний масив розмірності N*N, де кожен елемент визначається співвідношенням A[i,j]= Длязбереження ребер необхідний двовимірний масив розмірності M*2. Рядок такого масиву описує ребро. Для наведеного вище графу це буде 1 3 1 4 2 3 3 4
Спочатку помітимо усі вершини графу як нерозглянуті (т.т. заповнимо масив міток значенням true). Пошук почнемо з будь-якої вершиниv, наприклад з першої - значення мітки міняємо на протилежне (false - вершина розглянута). Опрацьовуємо дану вершину (наприклад, виводимо її номер) Для кожної вершини, яка суміжна з vі раніше не розглядалась, рекурсивно застосовуємо пошук в глибину. Будемо рахувати, що граф заданий матрицею суміжності, а для міток вершин використовується булевий масив Алгоритм пошуку в глибину (т. т. обходу всіх вершин графу)
Текст програми var a:array[1..100,1..100] of integer; cnt,n,i,j,k:integer; vert: array[1..100] of boolean; {процедура заповнення матриці суміжності з файлу} procedure inpt; var f:text; i,j:integer; begin assign(f,'in.dat'); reset(f); readln(f,n); for i:=1 to n do for j:=1 to n do read(f,a[i,j]); close(f); end;
{рекурсивна процедура пошуку в глибину} procedure seach_g(v:byte); var i:byte; Begin {опрацювання вершини} writeln(‘пройдено вершину ',v); vert[v]:=false; {вершина відвідана} for i:=1 to n do if (a[v,i]<>0) and vert[i] then begin {опрацювання вершини} seach_g(i); end; end;
{основна програма} Begin {заповнення матриці суміжності} inpt; {присвоєння міток усім вершинам} fillchar(vert,n,true); {лічильник компонент зв’язності} cnt:=0; {виклик процедури пошуку в глибину для чергової нерозглянутої вершини} for i:=1 to n do if vert[i] then begin {нарощування кількості компонент зв’язності} inc(cnt); seach_g(i) end; writeln(cnt); end.
2 3 5 4 8 9 6 7 Редагування файлу 1 1 2 5 3 4 Виклик процедури пошуку
Алгоритм перевірки графу на зв’язність(застосування пошуку в глибину) • В множину заносимо першу вершину • Рекурсивно для кожної вершини, яка зв'язана з нею, викликаємо процедуру, яка добавляє до множини ті вершини, з якими вона суміжна • Перевіряємо множину. Якщо вона містить N елементів, значить граф зв'язний, інакше – ні.
Текст програми • const n=10; • type mnog=set of 1..100; • var a:array[1..n,1..n] of integer; • i,k:integer; • vergr:mnog; • procedure svyaz(nr:integer;var versh:mnog); • var j:integer; • begin • for j:=1 to n do • if a[nr,j]<>0 then • if not(j in versh) then • begin • versh:=versh+[j]; • svyaz(j,versh); • end; • if nr=n then exit; • end; • begin • for i:=1 to n do • for k:=1 to n do • read(a[i,k]); • k:=1; • vergr:=[1]; • svyaz(k,vergr); • k:=0; • for i:=1 to n do • if i in vergr then begin writeln('=',i); k:=k+1; end; • if k=n then writeln(‘svyaznij’) else writeln(‘ne svyaznij’); • end.
1 3 2 1 1 3 3 2 2 4 4 Граф називається повним, якщо будь-які дві його вершини сполучені ребром. Повний граф має nвершин, то він матиме ребер. Граф без циклів – дерево. Остовне дерево(каркас) – дерево, в якому nвершин та n-1 ребер. 4 Мінімальний каркас : сума ваг усіх ребер, які входять до нього – мінімальна
Алгоритм побудови мінімального каркасу(Алгоритм Краскала) 1. к=0 2. поки к<= виконувати • пошук максимуму в матриці ваг • побудова матриці зв’язності, що відповідає графу з викинутим максимальним ребром • якщо граф зв’язний, то обнуляємо відповідний елемент в обох матрицях, збільшуємо к на 1 і переходимо до п.2 , інакше в матриці ваг робимо від’ємним значення максимуму і йдемо на п.2 3. знаходимо суму модулів елементів матриці ваг над головною діагоналлю(це і буде мінімальний каркас)
1 8 2 9 13 2 1 16 7 18 5 3 10 5 4 Приклад Видалення ребра 5-3 (18) 1 8 2 Видалення ребра 1-4 (16) 9 13 2 1 16 7 5 3 10 5 4
1 8 2 Видалення ребра 5-2 (13) 9 13 2 1 7 5 3 10 5 4 1 8 2 Видалення ребра 5-4 (10) 9 2 1 7 5 3 10 5 4
1 8 2 Ребро 5-1 (9) видалити неможливо, тому видаляємо наступне ребро 1-2 (8) 9 1 2 7 5 3 5 4 1 2 Видаляємо ребро 2-4 (7) 9 2 1 7 5 3 5 4 1 2 9 Отримуємо мінімальний каркас, його вартість 9+2+1+5=17 2 1 5 3 5 4
Фрагменти програми procedure buld;{побудова матриці суміжності по матриці ваг} var i,j:integer; begin for i:=1 to n do for j:=1 to n do if a[i,j]<>0 then matr_svz[i,j]:=1 else matr_svz[i,j]:=0; end; begin inpt; buld; rebr:=n*(n-1) div 2; while rebr>n-1 do begin imax:=1; jmax:=1; for i:=1 to n do for j:=1 to n do if a[i,j]>a[imax,jmax] then begin imax:=i;jmax:=j; end;
matr_svz[imax,jmax]:=0; matr_svz[jmax,imax]:=0; {--perevirka na zvjazok---} k:=1; vergr:=[1]; flag:=0; svyaz(k,vergr); l:=0; for i:=1 to n do if i in vergr then l:=l+1; if l=n then begin a[imax,jmax]:=0; a[jmax,imax]:=0; rebr:=rebr-1; end else begin a[imax,jmax]:=-a[imax,jmax]; a[jmax,imax]:=-a[jmax,imax]; matr_svz[imax,jmax]:=1; matr_svz[jmax,imax]:=1; end; end; s:=0; for i:=1 to n do for j:=i+1 to n do s:=s+abs(a[i,j]); writeln('ostov=',s); end.
1 8 2 9 13 2 1 16 7 18 5 3 10 5 4 Перевірка програми 1 5 2 12 8 7 3 3 6 4 In.dat OSTOV_KR.EXE
Алгоритм пошуку в ширину (т. т. обходу всіх вершин графу) Алгоритм знаходження мінімального по кількості вершин шляху. Між деякими містами існує авіасполучення. Потрібно знайти мінімальний по кількості пересадок шлях з міста А в місто В (т.т. вказати перелік міст, в яких необхідно здійснити пересадку). Використаємо такі структури даних : масив А[1..N], в який ми будемо записувати номери вершин, що доступні на даний момент з активної вершини, масив B[1..N], i -тим елементом якого буде номер вершини, з якої ми попали в вершину А[i], масив C[1..N], i -тим елементом якого буде true – якщо вершина А[i] уже розглядалась і false – якщо не розглядалась.
Алгоритм • Ініціалізація : вибираємо активною вершину, зв’язану з містом А (наприклад, і). Записуємо в А[1] значення і, в В[1] – 0, в С[1] – true. • З і –го рядка матриці суміжності переносимо номери вершин, з якими зв’язана і- та вершина поступово у масив А. • У відповідні елементи масиву В записуємо значення і, а у С – ставимо true в ті комірки, номер яких співпадає з номером суміжної з і вершини, яку ми розглянули. • Повторюємо цей крок алгоритму для вершини, номер якої записаний в А[2] і т. д.
2 4 1 5 3 Редагування файлу IN.DAT Для даного прикладу першим кроком алгоритму масиви заповняться так Програма POSH_SHI.EXE
Тепер знайдемо шлях. Його шукаємо методом „зворотної розкрути”, т.т. ідемо від кінцевої вершини (шукаємо її номер в А), дивимось на відповідний елемент в В (це і буде номер вершини, з якої ми попали в дану). Тепер знову шукаємо вже цю вершину в А і, аналогічно, відповідний їй елемент В – частина маршруту, і т.д., доки не зустрінемо вершину, з якої ми мали відправитись – це і буде шуканий маршрут, тільки у зворотному порядку. • Для даного прикладу шлях з вершини 1 в 3 буде 1- 5 – 3.
begin inpt; for i:=1 to n do begin for k:=1 to n do write(matr_svz[i,k],' '); writeln; end; i:=1; a[i]:=vp; b[vp]:=0; c[vp]:=true; k:=i+1; repeat l:=k; for j:=1 to n do if (matr_svz[a[i],j]<>0)and(not(c[j])) then begin a[k]:=j; b[k]:=a[i]; c[a[k]]:=true; k:=k+1; end; i:=i+1; sum:=true; for j:=1 to n do sum:=sum and c[j]; i:=i+1; until sum; writeln('======='); for j:=1 to n do write(a[j],' '); writeln('*********'); str(vk,s); s:=' '+s;rozkr(vk); writeln(s); end. var matr_svz:array[1..100,1..100] of integer; a,b:array[1..100]of integer; c:array[1..100] of boolean; z,n,l,k,i,j,vp,vk:integer; sum:boolean; s:string; procedure inpt; var f:text; i,j:integer; begin assign(f,'in.dat'); reset(f); readln(f,n); readln(f,vp,vk); for i:=1 to n do for k:=1 to n do read(f,matr_svz[i,k]); close(f); end; procedure rozkr(w:integer); var i:integer; t:string; begin if w=vp then exit; for i:=1 to n do if a[i]=w then break; str(b[i],t); s:=' '+t+s; writeln(b[i]); rozkr(b[i]); end;
Алгоритм “хвильки” (вихід з лабіринту) • В стартову клітинку записуємо k (початкове значення 2) • Поки не досягнуто фінішної клітинки( або повторювати стільки раз, скільки в матриці є нульових елементів) в сусідні не рівні 1 клітинки записати значення к+1 • Збільшити значення к на 1, перейти на п. 2
Цікаві сайти та книги • Uoi.kiev.ua • Olymp.vinnica.ua • Ф. Меньшиков. Олимпиадные задачи по программированию.: Питер, 2006 • Ахо А.А., Хопкрофт Д.Э., Ульман Д.Д. Структуры данных и алгоритмы. М.: Вильямс, 2000. • Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы. Построение и анализ. М.: МЦНМО, 2000. • Липский В. Комбинаторика для программистов. М.: Мир, 1988. • Вирт Н. Алгоритмы и структуры данных. СПб: Невский диалект, 2001. • Окулов С.М. 100 задач по информатике. Киров: изд-во ВГПУ, 2000 • Вирт Н. Алгоритмы и структуры данных. Санкт-Петербург: “Невский диалект”, 2001 • Кристофидес Н. Теория графов. Алгоритмический подход.-М.: Мир, 1978 Мої координати : 2jak@ua.fm, д. т. 58-03-08