IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

 
 Ответить  Открыть новую тему 
> Графы. Фундаментальная система циклов связного графа
сообщение
Сообщение #1


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


Написала программу по псевдокоду...Но результат работы процедур не выдается....Не пойму в чем проблема...Пседокод прилагаю..заранее благодарю за помощь))

uses crt;
const
max=50;
type
TMatrix = array [1..max,1..max] of byte;
TArray = array [1..max] of integer;

var
i,j,m,k,z : integer;
num,ftr,masQ: TArray;
Matrix : TMatrix; {матрица смежности}
n ,nz: integer; {количество вершин графа}

procedure save(i,j,nz:integer);
begin
z:=i;
while z<>j do
begin
masQ[nz]:=z;
z:=ftr[z];
masQ[nz]:=j;
masq[nz]:=i;
end;
end;
procedure cicle(i:integer);
var
j:integer;

begin
k:=k+1;
num[i]:=k;
for j:=1 to n do
begin
if (Matrix[i, j]<>0) and (num[j]=0) then
begin
ftr[j]:=i;
cicle(j);
end
else if ftr[i]<>j then
begin
nz:=nz+1;
save(i,j,nz);
end;
end;
end;

begin
clrscr;

writeln('=======Фундаментальная система циклов связного графа====');

write('Введите количество вершин графа:');
readln(n);
writeln('Заполнение матрицы смежности');
for i:=1 to n do
for j:=1 to n do
begin
Write('(',i,',',j,')=');
read(Matrix[i,j]);
if Matrix[i,j] <> 0 then Matrix[i,j]:=1;
end;
{$endif}
//вывод матрицы смежностиж;
writeln('Матрица смежности');
for i:=1 to n do
begin
for j:=1 to n do
write(Matrix[i,j],' ');
writeln;
end;
writeln;


writeln('Результат :');
n:=0; m:=0;
for i:=1 to n do
begin
num[i]:=0; {ни одна вершина не посещалась}
ftr[i]:=0;
n:=n+1;
m:=m+(n*n);
m:= round(m / 2);
k:=1;
end;
for i:=1 to m-n+1 do
begin
masQ[i]:=0;
k:=0;
nz:=0;
cicle(i);

//вывод массивов num ftr;
write('num: ');
for i:=1 to n do
write(num[i]:3);
writeln;
write('ftr: ');
for i:=1 to n do
write(ftr[i]:3);
writeln;
write('masQ: ');
for i:=1 to n do
write(masQ[i]:3);
writeln;
write('nz: ');
write(nz);
writeln;
readln;
end;
end.

Прикрепленное изображение


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


1. Обрати внимание, что в этой задаче граф предлагается задавать не матрицей смежности, а списками смежности. Соответственно при инициализации в цикле m:=m+n*n; - совсем ахинея, не считая ввода матрицы смежностей. Хотя подойдёт и матрица, но в методичке предлагается научиться работать со списками.
2. Кроме того, masQ - это не массив чисел, а массив стеков. И в процедуре SAVE операция masQ[nZ]<=i означает занесение числа i в вершину стека (стека под номером nZ в массиве стеков masQ), а не примитивное присвоение. Соответственно и вывод на экран из стека и массива стеков будет иным.
3. В SAVE строка с номером 5 вне тела цикла.

Внимательно прочти теорию.

Нечестно манипулировать форумчанами выдавая механический перевод псевдокода за попытку разобраться в теме. Хотя несомненно много лучше постановки задачи с последующим "разрешением" сделать всё "под ключ".

Предвидя вопрос о стеке...
Стек можно реализовать в виде массива [0..max]. В [0] элементе будет храниться глубина стека, а начиная с 1-го элемента будет располагаться сам стек. Соответственно, массив стеков становится двумерным массивом. Занесение в стек номер nZ числа i будет
Inc(masQ[nZ][0]);
x:=masQ[nZ][0];
masQ[nZ][x]:=i;

И лучше всего эти строки оформить процедурой.

Или же стек можно реализовать в виде динамической структуры.

Сообщение отредактировано: Федосеев Павел -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


спасибо большое за помощь,просто мне преподаватель дал книгу эту и сказала следовать тупо коду,а на деле оказалось не все так просто


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Если непонятно - задавай вопросы. Конечно, если возможно - преподавателю, он увидит твою работу. Если в методичке слишком заумно, задай поиск в сети.
вот ссылки навскидку
"http://rain.ifmo.ru/cat/view.php/theory/graph-circuits-cuts/euler-2004",
"http://www.intuit.ru/department/algorithms/gaa/7/3.html"
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


Если быть честной непонятно мне вообще в процедуре Save c 3-5 строчку как оформить это...


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Я вижу так:
procedure Save(i, j, nZ : integer);
var
z : integer;
begin
z:=i; {1}
while (z<>j) and (z<>0) do {2}
begin
StackPush(masQ[nZ], z); {3}
z:=ftr[z]; {4}
end;
StackPush(masQ[nZ], j); {5}
StackPush(masQ[nZ], i); {5}
end;

Массив стеков я организовал по-детски - по принципу массива строк String. Каждый стек это массив, у которого в элементе с индексом [0] находится глубина стека (его длина):
type
{TStack - тип для хранения стека фундаментальных циклов.
Его размер равен цикломатическому числу связанного графа,
т.е. m-n+1 или в максимальном виде (max*max-max+1)
}
TListX = array [0..max] of integer;
TStack = array [1..max*max-max+1] of TListX;
var
masQ : TStack; {массив стеков}

{помещение элемента Elem в стек Stack}
procedure StackPush( var Stack : TListX; Elem : Byte);
var
i : integer;
begin
i:=Stack[0];
inc(i);
Stack[i]:=Elem;
Stack[0]:=i;
end;

Это не самый лучший способ, но для упрощения реализации сойдёт.

Сообщение отредактировано: Федосеев Павел -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


спасибо за помощь...как отблагодарить не знаю... smile.gif


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Недорого - 3 месяца активной помощи (ответов) страждущим на форуме (по согласованию с администрацией можно и без кандалов) или старушку через дорогу перевести lol.gif
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


Ой этим я и так занимаюсь....помогаю бедным и обездоленным.... rolleyes.gif


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


 
uses crt;
const
max=50;

type
TMatrix = array [1..max,1..max] of byte;
TArray = array [1..max] of integer;
TList = array[0..max]of integer;
Tstack = array[1..max*max-max+1]of TList;
var
i,j,m,k,z : integer;
num,ftr : TArray;
Matrix : TMatrix; {матрица смежности}
n ,nz : integer; {количество вершин графа}
masQ:TStack;

procedure StackPush(Stack:TList;Elem:byte);
var
i:integer;
begin
i:=Stack[0];
inc(i);
Stack[i]:=Elem;
Stack[0]:=i;
end;
procedure save(i,j,nz:integer);
var
z:integer;
begin
z:=i;
while (z<>j) and (z<>0) do
begin
StackPush(masQ[nz],z);
z:=ftr[z];
end;
StackPush(masQ[nz],j);
StackPush(masq[nz],i)
end;
procedure cicle(i:integer);
var
j:integer;

begin
k:=k+1;
num[i]:=k;

for j:=1 to n do
begin
if (Matrix[i, j]<>0) and (num[j]=0) then
begin
ftr[j]:=i;
cicle(j);
end
else if ftr[i]<>j then
begin
nz:=nz+1;
save(i,j,nz);
end;
end;
end;

begin
clrscr;

writeln('=======Фундаментальная система циклов связного графа====');

write('Введите количество вершин графа:');
readln(n);
writeln('Заполнение матрицы смежности');
for i:=1 to n do
for j:=1 to n do
begin
Write('(',i,',',j,')=');
read(Matrix[i,j]);
if Matrix[i,j] <> 0 then Matrix[i,j]:=1;
end;
{$endif}
//вывод матрицы смежностиж;
writeln('Матрица смежности');
for i:=1 to n do
begin
for j:=1 to n do
write(Matrix[i,j],' ');
writeln;
end;
writeln;

//процедура dfs;
writeln('Результат dfs');
n:=0; m:=0;
for i:=1 to n do
begin
num[i]:=0; {ни одна вершина не посещалась}
ftr[i]:=0;
n:=n+1;
m:=m+(n*n);
m:= m div 2;
k:=1;
end;
for i:=1 to m-n+1 do
begin
StackPush(masQ[i],0);
k:=0;
nz:=0;
cicle(i);


write('num: ');
for i:=1 to n do
write(num[i]:3);
writeln;
write('ftr: ');
for i:=1 to n do
write(ftr[i]:3);
writeln;
write('masQ: ');

writeln;
write('nz: ');
write(nz);
writeln;
readln;
end;
end.

Прошу прощения за мою тупость ...но есть проблема теперь и с выводом результата,хотя ошибок в процедурах вроде нет


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


masQ? Он представляет из себя массив от 1 до nZ - первый (внешний цикл от 1 до nZ), каждый стек представляет из себя массив переменной длины, в котором элемент с нулевым индексом содержит длину стека (внутренний цикл от 1 до masQ[i][0]):
  writeln('nZ:  ', nZ);
writeln('masQ: ');
for i:=1 to nZ do
begin
write(i, '. ');
for j:=1 to masQ[i][0] do
write(masQ[i][j]:3);
writeln;
end;


А можно замечания к коду?
- переменная n вводится, а чуть ниже ей присваивается 0.
- переменной m присваивается не то значение. смотри внимательно псевдокод
- стек странно инициализируется. достаточно обнулить длины каждого стека for i:=1 to m-n+1 do masQ[i][0]:=0;
- из основной программы cicle вызывается один раз с параметром 1 (см. псевдокод)
Это из того, что бросается в глаза.

Далее, когда я попытался несколько дней назад отладить собственный вариант псевдокода, по ходу выполнения программы возникали исключения вида "полез в чужую память". Пришлось дополнить условия в save. Это увидишь отладчиком включив опци проверки диапазонов {$R+, Q+}.

Плюс к этому, в circle формировалась пара-тройка "левых" циклов. Также лечится усложнением условия сохранения вновь найденного цикла.

Сообщение отредактировано: Федосеев Павел -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


Павел это снова я с вопросами...))))Почему n потом обнуляется??сначала я ее ввожу для заполнения матрицы смежности....а остальное по псевдокоду...вот с оформлением m я сама не очень уверена....,но в 7 строке...получается что если m-нечетное,то идет присваение целому ,десятичного числа..А так оно все работает запускается,но процедуры не выводят никаких результатов,а теория никак не помогает((((

uses crt;
const
max=50;
type
TMatrix = array [1..max,1..max] of byte;
TArray = array [1..max] of integer;
TList = array[0..max]of integer;
Tstack = array[1..max*max-max+1]of TList;
var
i,j,m,k,z : integer;
num,ftr : TArray;
Matrix : TMatrix; {матрица смежности}
n ,nz : integer; {количество вершин графа}
masQ:TStack;
procedure StackPush(Stack:TList;Elem:byte);
var
i:integer;
begin
i:=Stack[0];
inc(i);
Stack[i]:=Elem;
Stack[0]:=i;
end;
procedure Save(i, j, nZ : integer);
var
z : integer;
begin
z:=i;
while (z<>j) and (z<>0) do
begin
StackPush(masQ[nZ], z);
z:=ftr[z];
end;
StackPush(masQ[nZ], j);
StackPush(masQ[nZ], i);
end;
procedure cicle(i:integer);
var
j:integer;

begin
k:=k+1;
num[i]:=k;
for j:=1 to n do
begin
if (Matrix[i, j]<>0) and (num[j]=0) then
begin
ftr[j]:=i;
cicle(j);
end
else if ftr[i]<>j then
begin
nz:=nz+1;
save(i,j,nz);
end;
end;
end;

begin
clrscr;

writeln('=======Фундаментальная система циклов связного графа====');

write('Введите количество вершин графа:');
readln(n);
writeln('Заполнение матрицы смежности');
for i:=1 to n do
for j:=1 to n do
begin
Write('(',i,',',j,')=');
read(Matrix[i,j]);
if Matrix[i,j] <> 0 then Matrix[i,j]:=1;
end;
{$endif}
//вывод матрицы смежностиж;
writeln('Матрица смежности');
for i:=1 to n do
begin
for j:=1 to n do
write(Matrix[i,j],' ');
writeln;
end;
writeln;

//процедура dfs;
writeln('Результат dfs');
n:=0; m:=0;
for i:=1 to n do
begin
num[i]:=0; {ни одна вершина не посещалась}
ftr[i]:=0;
n:=n+1;
m:=m+(n*n);
end;
m:= m div 2;


for i:=1 to m-n+1 do
begin
masQ[i][0]:=0;
k:=0;
nz:=0;
cicle(1);
end;

//вывод массивов num ftr;
write('num: ');
for i:=1 to n do
write(num[i]:3);
writeln;
write('ftr: ');
for i:=1 to n do
write(ftr[i]:3);
writeln;
writeln('nZ: ', nZ);
writeln('masQ: ');
for i:=1 to nZ do
begin
write(i, '. ');
for j:=1 to masQ[i][0] do
write(masQ[i][j]:3);
writeln;
end;
end.


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Знаток
****

Группа: Пользователи
Сообщений: 481
Пол: Мужской
Реальное имя: Федосеев Павел

Репутация: -  9  +


Юль, ты делаешь все механически, не вникая.
Мне проще отдать тебе готовый код, чем объяснять.

В архиве две папки. В одной работающий код по псевдокоду, с учётом примечания, найденного в книге Окулова о том, что к сохранению цикла переходим не только когда j вершина не предыдущая для i, но и когда при построении дерева поиска в глубину i вершина встретилась после j (т.е. найдено обратное ребро - ведущее вверх).
Цитата
Поиск в глубину является естественным подходом, используемым для нахождения фундаментальных циклов. Строится каркас, а каждое обратное ребро порождает цикл относительно этого каркаса. Для вывода циклов необходимо хранить порядок обхода графа при поиске в глубину (номера вершин) — массив St, а для определения обратных ребер вершины следует «метить» (массив Gnum) в той очередности, в которой они просматриваются. Если для ребра <v,j> оказывается, что значение метки вершины с номером j меньше, чем значение метки вершины с номером i, то ребро обратное и найден цикл.


Во второй папке программа с аналогичной функциональностью, встретившаяся мне на одном из форумов. Топикстартер утверждал, что она из книги Иванов Б.Н. "Дискретная математика. Алгоритмы и программы." Она мне просто понравилась.

В обоих случаях я использовал пример из твоей методички. Кстати, в интернете она встречается в pdf и с внесёнными исправленями.

Сообщение отредактировано: Федосеев Павел -


Прикрепленные файлы
Прикрепленный файл  BaseCycle.zip ( 3.72 килобайт ) Кол-во скачиваний: 324
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Новичок
*

Группа: Пользователи
Сообщений: 21
Пол: Женский
Реальное имя: Джули

Репутация: -  0  +


Спасибо тебе большое,но я вникала я перерыла все учебники по этой теме...просто сложно когда препод по практике ничего толком на твои вопросы не отвечает...мне самой легче не тупо сделать а понять,а чтобы понять надо чтобы тебе на примере показали хотя бы что -то...чего у нас нет...


--------------------
ДЖУЛИ
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 13.09.2025 10:30
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name