Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шестакова.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
326.64 Кб
Скачать

3 Решение задачи о максимальном потоке аналитическим методом

Рисунок 9

РЕШЕНИЕ: С помощью алгоритма Форда-Фалкерсона найдем наибольший поток из 1 в 8.

Шаг 1. Выбираем произвольный поток, например, 1-2-5-8. Его пропускная способность равна минимальной из всех пропускных способностей входящих в него дуг, то есть 1. Уменьшаем пропускные способности дуг этого потока на 1, насыщенные дуги 2-5 и 5-8 вычеркиваем.

Шаг 2. Выбираем произвольный поток, например, 0-4-7-8. Его пропускная способность равна минимальной из всех пропускных способностей входящих в него дуг, то есть 1. Уменьшаем пропускные способности дуг этого потока на 1, насыщенную дугу 7-8 вычеркиваем.

Рисунок 10

Шаг 3. Выбираем произвольный поток 1-3-4-7-6-8. Его пропускная способность равна минимальной из всех пропускных способностей входящих в него дуг, то есть 1. Уменьшаем пропускные способности дуг этого потока на 1, насыщенные дуги 3-4, 4-7, 6-8вычеркиваем.

Рисунок 11

Поток в сети равен: 1+1+1=1+1+1=3.

Насыщенные дуги: 2-5, 5-8 , 7-8 , 3-4, 4-7, 6-8.

Начинаем расстановку пометок. Начальная вершина (источник) 1 имеет пометку 0.

4 Алгоритм программы

пуск

Сток помечен?

S = вершина с меткой i+1

k=k+1

Ввод матрицы

i = i-1

Выделение пути из истока в сток

D = Поиск ребра с минимальной пропускной способностью

Увеличение потока по всем ребрам из истока в сток

F = F+D

Обход вершин, смежных с S

i=0

S = исток

F = 0

существует вершина с пометкой k+1

5 Программа

Текст программы имеет следующий вид:

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, Menus, StdCtrls, Grids;

type

TForm1 = class(TForm)

Label1: TLabel;

Edit1: TEdit;

Label2: TLabel;

Edit2: TEdit;

Button1: TButton;

StringGrid1: TStringGrid;

Label3: TLabel;

Edit3: TEdit;

Label4: TLabel;

Edit4: TEdit;

Memo1: TMemo;

Button2: TButton;

procedure FormCreate(Sender: TObject);

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Edit2Change(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

const

MaxV=1000;

MaxE=30000;

free_=0;

bisy_ = 1;

Great=MaxLongint;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);

begin

close;

end;

procedure TForm1.Edit2Change(Sender: TObject);

var st,i,u: integer;

begin

st:=StrToInt(edit2.Text);

StringGrid1.RowCount:=st+1;

u:=StrToInt(edit2.Text);

for i:=1 to u do

StringGrid1.Cells[0, i] :=IntToStr(i) ;

end;

procedure TForm1.FormCreate(Sender: TObject);

var i,u: integer;

begin

StringGrid1.Cells[0, 0] := 'Ребро';

StringGrid1.Cells[1, 0] := 'x';

StringGrid1.Cells[2, 0] := 'y';

StringGrid1.Cells[3, 0] := 'z'; //вес ребра

end;

procedure TForm1.Button1Click(Sender: TObject);

var

i: integer;

n, m, last, s, t, x, y, z: longint;

v,l: array[1..MaxV] of longint;

adj, next, c, f: array[1..MaxE] of longint;

found: boolean;

MaxPOTOK: longint;

prev: array [1..MaxV] of longint;

Marked: array [1..MaxV] of byte;

que,poz: array [1..MaxE] of longint;

qb,qe: longint;

procedure Init(n,m: longint);

var

i: longint;

begin

for i:=1 to n do

begin

v[i] := free_;

l[i] := free_;

end;

for i:=1 to 2*m do

begin

adj[i] := free_;

c[i] := free_;

next[i] := free_;

f[i] := free_;

end;

last := 0;

end;

procedure AddEdge(x,y,z: longint);

begin

inc(last);

adj[last] := y;

c[last] := z;

if v[x] = free_ then

begin

v[x] := last;

end else

begin

next[l[x]] := last;

end;

l[x] := last;

end;

procedure ErrorMes;

begin

ShowMessage('Неверно введены входные данные!');

exit

end;

procedure Put(x: longint);

begin

inc(qe);

que[qe]:=x;

Marked[x]:=bisy_;

prev[x]:=que[qb];

end;

procedure InitQue(x: longint);

var

i: longint;

begin

for i:=1 to 2*m do

begin

Marked[i]:=free_;

poz[i]:=0;

end;

qb:=1;

qe:=1;

que[qe] := x;

Marked[x] := bisy_;

end;

procedure FindWay;

var

x,Min,cf: longint;

begin

InitQue(s);

while (qb<=qe)and(Marked[t]<>bisy_) do

begin

x:=v[que[qb]];

while adj[x]<>free_ do

begin

if (Marked[adj[x]]<>bisy_)and(c[x]-f[x]>0) then

begin

Put(adj[x]);

poz[adj[x]]:=x;

end;

x:=next[x];

end;

inc(qb);

end;

if Marked[t]=free_ Then

begin

Found:=False;

Exit;

end;

Min:=Great;

x:=t;

while prev[x]<>free_ do

begin

cf:=c[poz[x]]-f[poz[x]]{!};

if cf<Min Then Min:=cf;

x:=prev[x];

end;

x:=t;

while prev[x]<>free_ do

begin

f[poz[x]]:=f[poz[x]]+Min;

if c[poz[x]]<>free_ then

f[poz[x]+1]:=-f[poz[x]]

else f[poz[x]-1]:=-f[poz[x]];

x:=prev[x];

end;

end;

begin

n := StrToIntDef(Edit1.Text, 0);

//Количество ребер

m := StrToIntDef(Edit2.Text, 0);

if (n = 0) or (m = 0) then ErrorMes;

Init(n,m);

for i := 1 to m do

begin

x := StrToIntDef(StringGrid1.Cells[1, i],0);

y := StrToIntDef(StringGrid1.Cells[2, i], 0);

z := StrToIntDef(StringGrid1.Cells[3, i], 0);

if (x <= 0) or (y <= 0) or (z <= 0) then ErrorMes;

AddEdge(x,y,z);

AddEdge(y,x,0);

end;

s := StrToIntDef(Edit3.Text, 0); // Источник

t := StrToIntDef(Edit4.Text, 0); // Сток

if (s > n) or (s <= 0) or (t > n) or (t <= 0) then ErrorMes;

found:=true;

while found do FindWay;

MaxPOTOK := 0;

x := v[s];

while x <> free_ do

begin

if f[x] > 0 then

MaxPOTOK := MaxPotok + f[x];

x:=next[x];

end;

Memo1.Lines.Clear;

Memo1.Lines.Add('Максимальный поток в заданном графе равен: '+ IntToStr(MaxPotok))

end;

end.