Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
22
Добавлен:
28.06.2014
Размер:
42 Кб
Скачать
unit UGraph;

interface

uses  utype, classes,dialogs, graphics;

{$M+}

procedure ProcessMessages;  //Супер процедура от зависания

type TArrV = array of TV;
type TarrE = array of TR;
type TBoolMatrix = array of array of 0..1;



type TGraph = class
  public
     {Описанные в этой секции элементы доступны всем.}
  V: Tarrv;  // Массив вершин
  E: TarrE;  // Массив ребер
  //MatrixSm: TMatrix; // Матриц смежности и инциденции
  //Matrixinc: TMatrix;//Вычисляется процедурой CreateMatrix(...)
  Orgraph: boolean; // true - орграф.  Иначе - не орграф
  Vzves: boolean; // тру - взвешенный
  service: integer;  //сюда пишем каждый себе что нужно
  comment: string;  // Комментарий к графу
  Web: boolean;    //Является ли сетью?
  col: Tarrcol;
  minOstov: TGraph ;   //Минимальные остовы - по одному в каждой компоненте связности
  constructor Create; overload;
  constructor Create(num: integer);  overload;
  constructor Create(filename: string); overload;
  constructor Invert(G: tgraph);

  function klika: boolean;   //Тру если клика (Вычисляется процедурой Kilka(g));
  function Odnorod: boolean;   //Тру если однородный  (Вычисляется процедурой Kilka(g));

  //Удаление ребра  - G - Граф, E - Указатель на ребро
  function delete(Reb: TR): boolean; overload;
  //Удаление вершины  - G - Граф, V - Указатель на вершину
  function delete(Ver: TV): boolean;  overload;
  //Создание ребра - G - Граф, p1, p2 - Указатели на вершины - концы ребра.
  //Возвращается созданное ребро.
  function Create(p1, p2: TV): TR;   overload;
  //Создание вершины - G - Граф, x,y - координаты вершины. Возвращается вершина.
  function Create( x, y: integer): TV; overload;
  //Есть ли ребро в графе?
  function GetE(p1, p2: TV):tr;
  //Вернуть вершину по координатам и радиусу
  function GetVChoord(x, y: integer): TV;
  function GetEChoord(x, y: integer): TR;
  //Процедура проерки и исправления ошибок в графе
  procedure CheckGraph;
  //Отрисовка графа на канве
  procedure Draw(Canv: tcanvas;  small: boolean = false);
  //Процедура копирования графа g
  constructor assign(g: tgraph);
  //Сохранить граф в файл
  procedure SaveTofile(filename: string);
  //Есть ли вершина в графе?
  function ExistV(ver: TV): boolean;
  //Есть ли ребро в графе?
  function ExistE(reb: TR): boolean;
  //возвращает указатель на матицу смежности
  procedure GetMatrixSm(var PmatrixSm:tmatrix);
  //возвращает указатель на матицу инциденций
  procedure GetMatrixInc(var PmatrixInc:tmatrix);
  //procedure createMatrix;
  //процедурa возвращает массив инцидентных ребер
  //Если флаг 1, то ищутся только дуги, исх из ver
  //Если -1, то то ищутся только дуги, вх из ver
  //Если другой, то все.
  //Выводятся с индекса 0.
  function GetIncE(ver:tv; flag: integer  = 0): tstrings;
  //процедурa возвращает массив смежных вершин
  //Если флаг 1, то ищутся только вершины, смежные по исходящей дуге
  //Если -1, то то ищутся только вершины, смежные по входящей дуге
  //Если другой, то все.
  //Выводятся с индекса 0.
  function GetIncV(ver:tv; flag: integer  = 0): tstrings;
  procedure delete;              overload;
  //процедурa возвращает степень вершины
  //Если флаг 1, то считаются только исходящие дуги
  //Если -1, - только входящие дуги
  //Если другой, то все.
  function DegV(ver: TV; flag: integer=0): integer;
  //процедурa возвращает номер вершины в графе если 0 то нет
  function Num(ver: TV): integer; overLoad;
  //процедурa возвращает номер ребра в графе если 0 то нет
  function Num(reb: TR): integer; OverLoad;
  //Добавить к графу ребро
  function Add(reb: TR): boolean; overload;
  //Добавить к графу вершину
  function Add(ver: TV):boolean; overload;
   function Svyaz:boolean;//Тру если связан
//Поиск смежных вершин с возвратом их в массиве
  //Если флаг 1, то ищутся только вершины, смежные по исходящей дуге
  //Если -1, то то ищутся только вершины, смежные по входящей дуге
  //Если другой, то все.
  //Выводятся с индекса 1.
  function GetIncV2(ver:tv; flag: integer  = 0): Tarrv;
  //процедурa возвращает массив инцидентных ребер
  //Если флаг 1, то ищутся только дуги, исх из ver
  //Если -1, то то ищутся только дуги, вх из ver
  //Если другой, то все.
  //Выводятся с индекса 0.
  function GetIncE2(ver:tv; flag: integer  = 0): Tarre;
  //Поиск матрицы достижимости (i-ая строка - достижимые вершины для i-ой вершины)
    //Поиск матрицы достижимости (i-ая строка - достижимые вершины для i-ой вершины)
  function SearchReachMatrix:tboolmatrix;
  //True- Существует путь из S в F (для произв графа)
  function IsPath(S,F:TV):boolean;
  //rocedure FindConComponents(g:tgraph; lb:tstrings);
  //procedure FindStronglyConComponents(g:tgraph; lb:tstrings);
  //Поиск кротчайщего пути и его длины по алгоритму Дейкстры
  //S-начало пути,F-конец
  //Возвращает 1 в случае успеха, -1 - граф не взвешен или не ориент, или не связан
  //-2 - не существует пути
  function SearchMinPath(var G:tgraph;S,F:tv;var LengthMinPath:integer):shortint;
  //Поиск максимального потока (заносится в поля ребер) и минимального разреза (заносятся
  //Razr - ребра мин разреза
  //s,t - источник и сток
  //MaxStream - величина макс потока
  //Возвращает 1 в случае успеха
  //-1 если граф не является сетью
  //-2 если нет пути из s в t
  function SearchMaxStreamAndRazrez(var Razr:tgraph;s,t:tv;var MaxStream:integer):shortint;
  //Раскраскра графа эвристическим алгоритмом (не всегда является оптимальной)
  //ChromaticNumber - хроматическое число
  //Возвращает 1 в случае успеха
  //-1 - если граф ориентированный
  function Coloring(var ChromaticNumber:integer):shortint;
  //Сохранить граф в файл. Filename - имя файла. G - подграф
  procedure SaveImage(filename: string; g: tgraph = nil);
  //Создать из текстового файла с матрицей инциденции
  constructor CreatewithInc(filename: string);
  //Создать из текстового файла с матрицей смежности
  constructor CreatewithSm(filename: string);
 private
   {Описанные в этой секции элементы не доступны извне (за пределами класса, но доступны в пределах модуля).}
   {Здесь обычно находятся поля класса.}
 protected
   {Описанные в этой секции элементы доступны только классу и всем его потомкам.}
 published
   {Описанные в этой секции элементы доступны всем и отображаются в Object Inspector'e.}
 end;

procedure drawstr(Canv: tcanvas; xt1, yt1, xt2, yt2: real; tru: boolean; rad: integer);
{function unscalex(x: real; arrcol: colorarray): integer;
function scalex(x: real; arrcol: colorarray):  integer;
function unscaley(y: real; arrcol: colorarray): integer;
function scaley(y: real; arrcol: colorarray):  integer;
 }
type TArrG = array of ^TGraph;
var g: TGraph;

implementation

uses windows, math, IniFiles, sysutils, ufund, uostov, jpeg;
procedure ProcessMessages; //ПРоцедура от  зависания. Вставлять в большие циклы и рекурсии
var
  Msg: TMsg;
begin
  while true do
  begin
    if not PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then Break;
    if Msg.Message <> 18 then
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end;
end;


constructor TGraph.Create;
begin
  if self <> nil then begin
    delete;
    col:=G_arrcol;
    setlength(v,1);
    setlength(e, 1);
    new(E[0]);
    E[0]^:=TRC.Create;
    e[0].p1:=nil;
    new(v[0]);
    v[0]^:=TVc.Create;
    service:=0;
  end else
    self:=Tgraph.Create;
end;

function TGraph.delete(Ver: TV): boolean;
var
  i: integer;
  ts: tstrings;
begin
  result:=false;
  if Existv(ver) then begin
  ts:=GetIncE(ver);
  for i := 0 to ts.Count-1 do
    delete(tR(ts.Objects[i]));
  ts.Free;
  for i := Num(ver)+1 to high(V) do
    V[i - 1]:=V[i];
  setlength(v, length(v) - 1);
  //creatematrix;
  result:=true;
  end;

end;


function TGraph.delete(Reb: TR): boolean;
var
  i: integer;
begin
  result:=false;
  if ExistE(reb) then begin
  for i := num(reb) + 1 to high(e) do
    e[i - 1]:=e[i];
  setlength(e, length(e) - 1);
  result:=true;
    //creatematrix;
  end;
end;

function TGraph.Create(x, y: integer): TV;
begin
  setlength(v, length(v) + 1);
  new(v[high(v)]);//:=tv.Create;
  v[high(v)]^:=tvC.Create;
  v[high(v)].x := x;
  v[high(v)].y := y;
  v[high(v)].move:=false;
  v[high(v)].status := col^.colorV;
  v[high(v)].color:=clWhite;
  result := v[high(v)];

  //creatematrix;

end;

function TGraph.Create(p1, p2: TV): TR;
begin
  result:=nil;
   if (p1<>p2)  and (GetE(p1, p2) = nil) then begin
     setlength(E, length(E) + 1);
     new(E[high(E)]);
     E[high(E)]^:=TRc.Create;
     E[high(E)].p1:=p1;
     E[high(E)].p2:=p2;
     E[high(E)].ves:=0;
     E[high(e)].status:=col^.colore;
     result := E[high(E)];
     //creatematrix;

   end;

end;

function TGraph.GetE(p1, p2: TV):tr;
var i: integer;
begin
  Result:=nil;
  if Orgraph then begin
    for i := 1 to High(e) do
      if (e[i].p1 = p1) and (e[i].p2 = p2) then begin
        result:=e[i];
        break;
      end
  end else begin
    for i := 1 to High(e) do
      if ((e[i].p1 = p1) and (e[i].p2 = p2)) or ((e[i].p1 = p2) and (e[i].p2 = p1))then begin
        result:=e[i];
        break;
      end;
  end
end;


function TGraph.GetVChoord(x, y: integer): TV;
var i: integer;
begin
  result:=nil;
  for i := 1 to High(V) do
    if sqr(v[i].x - x) +sqr(v[i].y - Y)< sqr(col.rad) then begin
      result:=v[i];
      break;
    end
end;

function TGraph.GetEChoord(x, y: integer): TR;
var i: integer;
q:real;
RE: tr;
begin
  result:=nil;
  for i := 1 to High(e) do begin
    if E[i].p1.x <> E[i].p2.x then begin
      re:=GetE(e[i].p2, e[i].p1) ;
      if re = nil then begin
        q := (E[i].p2.y - E[i].p1.y) /(E[i].p2.x - E[i].p1.x) * (x - E[i].p1.x)+ E[i].p1.y;
        if ((x >= min(E[i].p1.x, E[i].p2.x) - col^.delta) and
          (x <= max(E[i].p1.x, E[i].p2.x) + col^.delta) and
          (y >= q - col^.delta) and
          (y <= q+ col^.delta)) then begin
            result:= e[i];
            break;
          end;
      end else begin
        if ((x >= min(E[i].p1.x, E[i].p2.x) - col^.delta) and (x <= (max(E[i].p1.x, E[i].p2.x)+ min(E[i].p1.x, E[i].p2.x))/2 + col^.delta)) then begin
           q := (E[i].p2.y - E[i].p1.y) /(E[i].p2.x - E[i].p1.x) * (x - E[i].p1.x)+ E[i].p1.y;
          if ((y >= q - col^.delta) and(y <= q+ col^.delta)) then begin
            result:= re;
            break;
          end;
        end else if ((x <= mAx(E[i].p1.x, E[i].p2.x) + col^.delta) and (x >= (max(E[i].p1.x, E[i].p2.x)+ min(E[i].p1.x, E[i].p2.x))/2 + col^.delta)) then begin
           q := (E[i].p2.y - E[i].p1.y) /(E[i].p2.x - E[i].p1.x) * (x - E[i].p1.x)+ E[i].p1.y;
          if ((y >= q - col^.delta) and(y <= q+ col^.delta)) then begin
            result:= e[i];
            break;
          end;
        end;
      end;
    end else begin
      re:=GetE(e[i].p2, e[i].p1) ;
      if re = nil then begin
        if ((x >= E[i].p1.x - col^.delta) and
          (x <= E[i].p1.x+col^.delta) and
          (y >= min(E[i].p1.y, E[i].p2.y) - col^.delta) and
          (y <= max(E[i].p1.y, E[i].p2.Y)+ col^.delta)) then begin
            result := e[i];
            break;
          end;
      end else begin
        if ((x >= E[i].p1.x - col^.delta) and (x <= E[i].p1.x+col^.delta)) then
          if((y >= (min(E[i].p1.y, E[i].p2.y)+max(E[i].p1.y, E[i].p2.Y))/2 - col^.delta) and
            (y <= max(E[i].p1.y, E[i].p2.Y)+ col^.delta)) then begin
            result :=re;
            break;
          end else if((y <= (min(E[i].p1.y, E[i].p2.y)+max(E[i].p1.y, E[i].p2.Y))/2 - col^.delta) and
            (y >= min(E[i].p1.y, E[i].p2.Y)+ col^.delta)) then begin
            result :=  e[i];
            break;
          end;
      end;
    end;
  end;
end;

function TGraph.Odnorod: boolean;
var i: integer;
begin
  result:=true;
  if Orgraph then begin
    if high(V) > 1 then  begin
      for i := 2 to high(V) do
        if DegV(V[i], 1) <> degv(V[1], 1) then begin
          result:=false;
          break;
        end;
    end;
  end else begin
    if high(V) > 1 then  begin
      for i := 2 to high(V) do
        if DegV(V[i]) <> degv(V[1]) then begin
          result:=false;
          break;
        end;
    end;
  end;
end;

function TGraph.klika: boolean;
begin
  if Orgraph then begin
    if odnorod then  begin
      if high(v)>1 then
        if DegV(v[1], 1) = high(v)-1 then
          result:=true
        else
          result:=false
      else
        result:=true;
    end else
      result:=false;
  end else begin
    if odnorod then  begin
      if high(v)>1 then
        if DegV(v[1]) = high(v)-1 then
          result:=true
        else
          result:=false
      else
        result:=true;
    end else
      result:=false;
  end;
end;

constructor TGraph.Create(num: integer);
var i, j: integer;
begin
  create;
  try
    for i := 1 to num do begin
      Create(round(cos(2*PI*i/num)*100+150), round(sin(2*PI*i/num)*100+150));
      for j := 1 to i-1 do
       create(V[i], V[j]);
    end;
  except
  end;
  comment:='Клика '+ inttostr(num);
end;



constructor TGraph.Create(filename: string);
var graphfile: TIniFile;
hgv, hge, i: integer;
ves: integer;
ver: tv;
tv: tr;
begin
Create;
  try
    graphfile:=tinifile.Create(FileName);
    hgv:= graphfile.readInteger('graph', 'Vount', -1);
    hge:= graphfile.ReadInteger('graph', 'Eount', -1);
    Orgraph:=graphfile.readbool('graph', 'Orgraph', false);
    vzves:=graphfile.readbool('graph', 'Vzves', false);
    web:=graphfile.readbool('graph', 'Web', false);
    comment:=graphfile.readString('graph', 'Comment', '');
    for i := 1 to hgv do begin
      Create(graphfile.readinteger('V'+inttostr(i), 'X', 0), graphfile.readInteger('V'+inttostr(i), 'y', 0)).color:=clwhite;
    end;
    for i := 1 to hge do begin
      tv:= create(V[graphfile.readInteger('E'+inttostr(i), 'P1', -1)],V[graphfile.readInteger('E'+inttostr(i), 'P2', -1)]);
      ves:=graphfile.readInteger('E'+inttostr(i), 'Ves', 0);
      E[i].potok:=   graphfile.readInteger('E'+inttostr(i), 'Potok', 0);
      tv^.ves:=ves;
    end;
    graphfile.Free;
  except
  end;
end;

procedure TGraph.CheckGraph;
var i, j: integer;
begin
  if not Orgraph then begin
    i:=1;
    while i <= high(e) do
      if (e[i].p1 = nil) or (e[i].p2 = nil) then
        delete(e[i])
      else begin
        j:=1;
        while j < i do
          if ((e[j].p1 = E[i].p1) and (e[j].p2 = E[i].p2)) or ((e[j].p1 = E[i].p2) and (e[j].p2 = E[i].p1)) then begin
            delete(E[i]);
            break;
          end else
            j:=j+1;
        if j = i then
          inc(i);
      end
  end else
  //createMatrix;
end;


procedure TGraph.GetMatrixSm(var PmatrixSm:tmatrix);
var i, j, k: integer;
//MatrixSm: TMatrixC;
begin
  //MatrixSm.Free;
  new(PmatrixSm);

  pmatrixsm^:=TMatrixC.create(high(V), high(V));
  for i := 1 to high(v) do
    for j := 1 to high(V) do
      pmatrixsm.Matrix[i, j]:=0;
  if Orgraph then
    for i := 1 to high(E) do begin
      j:=1;
      k:=1;
      while j<=high(V) do
        if V[j] = E[i].p1 then break
        else j:=j+1;
      while k<=high(V) do
        if V[k] = E[i].p2 then break
        else k:=k+1;
      pmatrixsm.Matrix[j, k]:=1;
    end
  else
    for i := 1 to high(E) do begin
      j:=1;
      k:=1;
      while j<=high(V) do
        if V[j] = E[i].p1 then break
        else j:=j+1;
      while k<=high(V) do
        if V[k] = E[i].p2 then break
        else k:=k+1;
      if (j <= high(v))and (K <= high(v)) then begin
         pmatrixsm.Matrix[j, k]:=1;
         pmatrixsm.Matrix[k, j]:=1;
      end;
    end;
    //n:=high(v);
   // m:=high(v);
    //PmatrixSm:=addr(pmatrixsm);
end;

procedure TGraph.GetMatrixInc(var PmatrixInc:tmatrix);
var i, j, k: integer;
//MatrixInc: TMatrixC;
begin
  //pMatrixinc.Fre
  new(PmatrixInc);
  pMatrixinc^:=TMatrixC.create(length(V),length(e));
  for i := 1 to high(v) do
    for j := 1 to high(e) do
      pMatrixinc.Matrix[i, j]:=0;
  if Orgraph then
    for i := 1 to high(E) do begin
      j:=1;
      k:=1;
      while j<=high(V) do
        if V[j] = E[i].p1 then break
        else j:=j+1;
      while k<=high(V) do
        if V[k] = E[i].p2 then break
        else k:=k+1;
      pMatrixinc.Matrix[j,i]:=1;
      pMatrixinc.Matrix[k,i]:=-1;
    end
  else
    for i := 1 to high(E) do begin
      j:=1;
      k:=1;
      while j<=high(V) do
        if V[j] = E[i].p1 then break
        else j:=j+1;
      while k<=high(V) do
        if V[k] = E[i].p2 then break
        else k:=k+1;
      pMatrixinc.Matrix[k,i]:=1;
      pMatrixinc.Matrix[j,i]:=1;
    end;
 { n:=high(v);
  m:=high(e);
  PmatrixInc:=addr(MatrixInc);  }
end;



procedure TGraph.Draw(Canv: tcanvas;  small: boolean = false);
var
  i: integer;
  num:string;
  numi:  integer;
begin
  //Canv.Lock;
  if not small then begin
  canv.Pen.Width:=1;
  Canv.Refresh;
  Canv.Pen.Color := col^.Rect;
  Canv.Rectangle(0, 0, col^.he, col^.wi);
  end;
  { -------Отрисовка вершин ------- }
  if col^.ShowNameV then
    for i := 1 to high(V) do begin
      if small then begin
        canv.Pen.Color:=col^.selV;
        canv.Pen.Width:=2;
      end else begin
        Canv.Pen.Color := V[i].status;
        canv.Pen.Width:=1;
      end;
      if V[i].status= col^.movev then V[i].status:= (col^.colorV);
      numi:=g.Num(v[i]);
      if numi <> 0 then
        Canv.brush.Color := g.V[numi].color
      else begin
        Canv.brush.Color := v[i].color;
        numi:=i;
      end;
      num:=inttostr(numi);
      Canv.Ellipse(V[i].x - col^.rad, V[i].y - col^.rad,
        V[i].x + col^.rad,V[i].y + col^.rad);
      Canv.Brush.color := clwhite;
      Canv.font.Color := clblack;
      canv.Font.Height:=col^.sizefont;
      Canv.Brush.Style := bsClear;
      Canv.TextOut(V[i].x - round(Canv.TextWidth(num)/2), V[i].y -round(canv.TextHeight(num)/2), num);
      Canv.Brush.Style := bsSolid;
    end
  else
      for i := 1 to high(V) do
      begin
      if small then begin
        canv.Pen.Color:=col^.selV;
        canv.Pen.Width:=2;
      end else begin
        Canv.Pen.Color := V[i].status;
        canv.Pen.Width:=1;
      end;
        Canv.brush.Color := g.V[g.Num(V[i])].color;
        Canv.Ellipse(V[i].x - col^.rad, V[i].y - col^.rad,V[i].x + col^.rad,V[i].y + col^.rad);
        Canv.Brush.color := clwhite;

      end;
  { ------------Отрисовка ребер--------- }
  for i := 1 to high(e) do
  begin
      if small then begin
        canv.Pen.Color:=col^.sele;
        canv.Pen.Width:=2;
      end else begin
        Canv.Pen.Color := e[i].status;
        canv.Pen.Width:=1;
      end;
    if E[i].status= col^.mEvee then E[i].status:= col^.colorE;
    drawstr(Canv, e[i].p1.x,e[i].p1.y,e[i].p2.x,e[i].p2.y, Orgraph or Web,
      round(col^.rad*col^.scale/100)
      );
  end;
  if web then
    for i := 1 to high(e) do begin
      if e[i].potok > 0 then
        canv.textout(round((E[I].p1.x+E[i].p2.x)/2),round((E[I].p1.y+E[i].p2.y)/2), inttostr(e[i].potok)+' ['+inttostr(E[i].ves)+']')
      else
        canv.textout(round((E[I].p1.x+E[i].p2.x)/2),round((E[I].p1.y+E[i].p2.y)/2),'['+inttostr(E[i].ves)+']')
    end
  else
    if col^.ShownameE then begin
      if col^.ShowVes and Vzves then
        for i := 1 to high(e) do begin
          numi:=g.Num(e[i]);
          if numi = 0 then
            numi:=i;
          num:=inttostr(numi);
          canv.textout(round((E[I].p1.x+E[i].p2.x)/2),round((E[I].p1.y+E[i].p2.y)/2), 'e'+num+' ('+inttostr(E[i].ves)+')')
        end
      else
        for i := 1 to high(e) do begin
          numi:=g.Num(e[i]);
          if numi = 0 then
            numi:=i;
          num:=inttostr(numi);
          canv.textout(round((E[I].p1.x+E[i].p2.x)/2), round((E[I].p1.y+E[i].p2.y)/2), 'e'+num)
        end
    end else
      if col^.ShowVes and Vzves then
        for i := 1 to high(e) do
          canv.textout(Round((E[I].p1.x+E[i].p2.x)/2), Round( (E[I].p1.y+E[i].p2.y)/2), '('+inttostr(E[i].ves)+')');
    {------------Отрисовка ребер--------- }
//  Canv.unLock;
end;

procedure drawstr(Canv: tcanvas; xt1, yt1, xt2, yt2: real; tru: boolean;
  rad: integer);
var
  X1, x2, y1, y2: real;
  x3, x4, y3, y4: real;
  x5, y5, ox, oy: real;
begin
  if not((xt1=xt2)  and (yt1 = yt2)) then begin

  X1 := rad * (xt2 - xt1) / sqrt(sqr(xt1 - xt2) + sqr(yt1 - yt2)) + xt1;
  y1 := rad * (yt2 - yt1) / sqrt(sqr(xt1 - xt2) + sqr(yt1 - yt2)) + yt1;
  x2 := rad * (xt1 - xt2) / sqrt(sqr(xt1 - xt2) + sqr(yt1 - yt2)) + xt2;
  y2 := rad * (yt1 - yt2) / sqrt(sqr(xt1 - xt2) + sqr(yt1 - yt2)) + yt2;
  if (X1 <> x2) or (y1 <> y2) then
  begin
    x5 := abs(((x2 - X1) * rad / sqrt(sqr(x2 - X1) + sqr(y2 - y1))) - x2);
    y5 := abs(((y2 - y1) * rad / sqrt(sqr(x2 - X1) + sqr(y2 - y1))) - y2);
    ox := (x2 - (x2 - x5));
    oy := (y2 - (y2 - y5));
    x3 := (ox - (y2 - y5) / 5);
    y3 := (oy + (x2 - x5) / 5);
    x4 := (ox + (y2 - y5) / 5);
    y4 := (oy - (x2 - x5) / 5);
   // Canv.Pen.Width := 1;
    // canv.Pen.Style:=psSolid;
    with Canv do
    begin
      moveto(round(X1), round(y1));
      LineTo(round(x2), round(y2));
      if tru then
      begin
        Canv.Pen.Width:=Canv.Pen.Width+1;
        LineTo(round(x3), round(y3));
        moveto(round(x2), round(y2));
        LineTo(round(x4), round(y4));
        Canv.Pen.Width:=Canv.Pen.Width-1;
      end;
    end;
  end;
end;
end;

constructor TGraph.assign(g: tgraph);
var i: integer;
begin
  create;
  setlength(v, length(g.V));
  for i := 0 to high(g.V) do begin
    v[i]:=g.V[i];
  end;
  setlength(E, length(g.e));
  for i := 0 to high(g.E) do begin
    E[i]:=g.E[i];
  end;
  Orgraph:=g.Orgraph;
  Vzves:=g.Vzves;
  comment:=g.comment;
  service:=g.service;
  //createMatrix;
end;

procedure TGraph.SaveTofile(filename: string);
var graphfile: Tinifile;
  i: integer;
begin
  graphfile:=tinifile.Create(FileName);
  graphfile.WriteInteger('graph', 'Vount', high(V));
  graphfile.WriteInteger('graph', 'Eount', high(E));
  graphfile.writebool('graph', 'Orgraph', Orgraph);
  graphfile.writebool('graph', 'Vzves', vzves);
  graphfile.writebool('graph', 'Web', Web);
  graphfile.WriteString('graph', 'Comment', comment);
  for i := 1 to high(V) do begin
    graphfile.WriteInteger('V'+inttostr(i), 'X', V[i].x);
    graphfile.WriteInteger('V'+inttostr(i), 'y', V[i].Y);
//    graphfile.WriteString('V'+inttostr(i), 'Comment', V[i]^.comment);
  end;
  for i := 1 to high(e) do begin
    graphfile.WriteInteger('E'+inttostr(i), 'P1', Num(e[i].p1));
    graphfile.WriteInteger('E'+inttostr(i), 'P2', num(e[i].p2));
    graphfile.WriteInteger('E'+inttostr(i), 'Ves', E[i].ves);
    graphfile.WriteInteger('E'+inttostr(i), 'Potok', E[i].potok);
  end;
  graphfile.Free;
end;

function TGraph.ExistV(ver: TV): boolean;
var i: integer;
begin
  result:=false;
  for i := 1 to high(v) do
    if v[i] = ver then begin
      result:=true;
      break;
    end;
end;


function TGraph.ExistE(reb: Tr): boolean;
var i: integer;
begin
  result:=false;
  for i := 1 to high(e) do
    if e[i] = reb then begin
      result:=true;
      break;
    end;
end;

procedure TGraph.Delete;
var i: integer;
begin
try
  for i := 1 to high(v) do
    v[i]^.Free;
  for i := 1 to high(e) do
    E[i]^.Free;
  setlength(v, 1);
  setlength(e, 1);
except
end;
end;

function TGraph.GetIncE(ver:tv; flag: integer  = 0): tstrings;
var i: integer;
  TS: tstrings;
begin
  ts:=TStringList.Create;
  ts.Clear;
  case flag  of
  1:for i := 1 to high(e) do
      if e[i].p1 = ver then
        ts.addobject('', tobject(e[i]));
  -1:for i := 1 to high(e) do
      if e[i].p2 = ver then
        ts.addobject('', tobject(e[i]));
  else
    for i := 1 to high(e) do
      if (e[i].p1 = ver) or (e[i].p2 = ver) then
        ts.addobject('', tobject(e[i]));
  end;
  result:=ts;
end;

function TGraph.GetIncV(ver:tv; flag: integer  = 0): tstrings;
var i: integer;
  TS: tstrings;
begin
  ts:=TStringList.Create;
  ts.Clear;
  case flag  of
  1:for i := 1 to high(e) do
      if e[i].p1 = ver then
        ts.addobject('', tobject(e[i].p2));
  -1:for i := 1 to high(e) do
      if e[i].p2 = ver then
        ts.addobject('', tobject(e[i].p1));
  else
    for i := 1 to high(e) do
      if (e[i].p1 = ver) then
        ts.addobject('', tobject(e[i].p2))
      else if  (e[i].p2 = ver)  then
        ts.addobject('', tobject(e[i].p1))
  end;
  result:=ts;
end;

function TGraph.DegV(ver: TV; flag: integer=0): integer;
var i: integer;
begin
  result:=0;
  case flag of
    1: for i := 1 to high(e)  do
      if e[i].p1 = ver then
        inc(result);
    -1: for i := 1 to high(e)  do
      if (e[i].p2=ver) then
        inc(result);
    else
      for i := 1 to high(e)  do
        if (e[i].p1=ver) or ( e[i].p2=ver)  then
          inc(result);
  end;
end;

function TGraph.Num(reb: TR): integer;
var i: integer;
begin
  result:=0;
  for i := 1 to high(e) do
    if reb = e[i] then begin
      result:=i;
      break;
    end;
end;


function TGraph.Num(ver: TV): integer;
var i: integer;
begin
  result:=0;
  for i := 1 to high(V) do
    if ver = V[i] then begin
      result:=i;
      break;
    end;
end;

function TGraph.Add(reb: TR): boolean;
begin
  result:=false;
  if (reb <> nil ) and not ExistE(reb) then begin
    setlength(e, length(e)+1);
    e[high(e)]:=reb;
    result:=true;
  end;
end;

function TGraph.Add(ver: TV): boolean;
begin
  result:=false;
  if not ExistV(ver) then begin
    result:=true;
  setlength(v, length(v)+1);
  v[high(v)]:=ver;
  end;
end;

function TGraph.Svyaz:boolean;
begin
//if length(TSsvyaz)=1 then
  result:=true
//else
  //result:=false;
end;


function TGraph.GetIncV2(ver:tv; flag: integer  = 0): Tarrv;
var i: integer;
 adj:Tarrv;
begin
  SetLength(adj,1);

  case flag  of
  1:for i := 1 to high(e) do
      if e[i].p1 = ver then
      begin
         SetLength(adj,length(adj)+1);
         adj[high(adj)]:=e[i].p2;
      end;


  -1:for i := 1 to high(e) do
      if e[i].p2 = ver then
       begin
         SetLength(adj,length(adj)+1);
         adj[high(adj)]:=e[i].p1;
      end;

  else
    for i := 1 to high(e) do
      if (e[i].p1 = ver) then
        begin
         SetLength(adj,length(adj)+1);
         adj[high(adj)]:=e[i].p2;
      end

      else if  (e[i].p2 = ver)  then
        begin
         SetLength(adj,length(adj)+1);
         adj[high(adj)]:=e[i].p1;
      end;

  end;
  result:=adj;
  //SetLength(adj,0);
  //adj:=nil;
end;

function TGraph.GetIncE2(ver:tv; flag: integer  = 0): Tarre;
var i: integer;
  Adj:tarre;
begin
  SetLength(adj,1);
  //ts:=TStringList.Create;
  //ts.Clear;
  case flag  of
  1:for i := 1 to high(e) do
      if e[i].p1 = ver then
      begin
        SetLength(adj,length(adj)+1);
        adj[high(adj)]:=e[i];
      end;
        //ts.addobject('', tobject(e[i]));
  -1:for i := 1 to high(e) do
      if e[i].p2 = ver then
      begin
        SetLength(adj,length(adj)+1);
        adj[high(adj)]:=e[i];
      end;
  else
    for i := 1 to high(e) do
      if (e[i].p1 = ver) or (e[i].p2 = ver) then
      begin
        SetLength(adj,length(adj)+1);
        adj[high(adj)]:=e[i];
      end;
  end;
  result:=adj;
end;

function TGraph.SearchMinPath(var G:tgraph;S,F:tv;var LengthMinPath:integer):shortint;
const contin = 100000;//этим значением инициализируются метки Labels (типа бескон-ть), изменить, если будут отрицат веса

type TLabels = record
  L: integer;
  ConstL: boolean; //true -если метка постоянная(L-точное значение длины мин пути из S в V)
                    //false- L -временных метка для вершины(верхняя оценка длины мин пути из S в V)
end;
var
Labels:array of tlabels;
i,j:integer;
ver:tv;//текущая вершина
minl:integer;//значение мин labels
Indmin:integer;//номер вершины,c labels=minl

begin
if not (Vzves and Orgraph and Svyaz)  then
begin
  result:=-1;
  exit;
end;
if IsPath(s,f)=false then
begin
  result:=-2;
  exit;
end;

//поиск меток и длины пути
SetLength(Labels,Length(v));

for i := 1 to high(V) do
begin
  Labels[i].l:=contin;
  Labels[i].ConstL:=false;
end;
Labels[Num(s)].l:=0;
Labels[Num(s)].ConstL:=true;
ver:=s;

//с исполь GetIncV
{repeat
  Indmin:=1;
  minl:=Labels[num(tv(GetIncV(ver,1).objects[1]))];
  for j := 1 to DegV(ver) do
  begin
    tempLabels[num(tv(GetIncV(ver,1).objects[j]))] := min(tempLabels[num(tv(GetIncV(ver,1).objects[j]))],templabels[num(ver)]+GetE(ver,tv(GetIncV(ver,1).objects[j])).ves);
    if tempLabels[num(tv(GetIncV(ver,1).objects[j]))]<minl then
    begin
      Indmin:=j;
      minl:=tempLabels[num(tv(GetIncV(ver,1).objects[j]))];
    end;
  end;
  ver:=tv(GetIncV(ver,1).objects[indmin]);
  Labels[num(ver)]:=TempLabels[num(ver)];
until Labels[Num(f)]<>0;      }

repeat
  for j := 1 to DegV(ver,1) do
  begin
    //ShowMessage(inttostr(tempLabels[num(GetIncV2(ver,1)[j])]));
    //ShowMessage(inttostr(templabels[num(ver)]{+GetE(ver,GetIncV2(ver,1)[j]).ves}));
    if labels[num(GetIncV2(ver,1)[j])].ConstL=false then
      Labels[num(GetIncV2(ver,1)[j])].l := min(Labels[num(GetIncV2(ver,1)[j])].l,labels[num(ver)].l+GetE(ver,GetIncV2(ver,1)[j]).ves);

  end;
  Indmin:=1;
  minl:=contin;
  for j := 1 to high(labels) do
  if (Labels[j].l<minl) and (Labels[j].ConstL=false) then
    begin
      Indmin:=j;
      minl:=Labels[j].l;
    end;
  ver:=v[indmin];
  Labels[num(ver)].ConstL:=true;
until Labels[Num(f)].ConstL;

LengthMinPath := Labels[Num(f)].L;


//поиск маршрута
ver:=f;
g:=tgraph.create;
SetLength(g.V,2);
SetLength(g.E,1);
g.V[1]:=f;
repeat
  i:=1;
  repeat
//for i := 1 to degv(ver,-1) do

  if Labels[num(ver)].L=labels[num(GetIncV2(ver,-1)[i])].L+gete(GetIncV2(ver,-1)[i],ver).ves then
  begin
    SetLength(g.V,length(g.V)+1);
    g.V[high(g.V)]:=GetIncV2(ver,-1)[i];
    SetLength(g.e,length(g.e)+1);
    g.e[high(g.e)]:=gete(GetIncV2(ver,-1)[i],ver);
    ver:=GetIncV2(ver,-1)[i];
    break;
  end;

  //ShowMessage(inttostr(degv(ver,-1)));
  inc(i);
  until i=DegV(ver,-1)+1;
until ver=s;

SetLength(Labels,0);
Labels:=nil;
result:=1;
end;



function Tgraph.SearchReachMatrix:tboolmatrix;
var R:TBoolMatrix;
  i,j:integer;
  MatrixSm:tmatrix;
  //m,n:integer;//размеры м-цы смежности
//процедура добавления вершин в R,достижимых из данной
                     //x-номер текущей вершины,count-номер строки в R
Procedure Component( x,count :Integer);
var
  i :Integer;
begin

R[count][x]:= 1;

for i:=1 to high(V) do
  //если вершина смежна с текущей и это не петля
  if (MatrixSm.Matrix[x,i] = 1) and (x<>i)   then
  begin
    //если ее не обходили
   if R[count,i] = 0 then
      Component(i,count);
  end;
end;



begin
//new(matrixsm);
GetMatrixSm(MatrixSm);
//new(matrixsm);
//MatrixSm.create(m,n);
//showmessage(inttostr(MatrixSm.Matrix[0,0]));
SetLength(R,high(V)+1,high(V)+1);
//showmessage(inttostr(MatrixSm.Matrix[0,0]));
for i := 1 to high(V) do
  for j := 1  to high(V) do
    R[i,j]:=0;

for i := 1 to high(V) do
      Component(i,i);

result:=r;

setlength(MatrixSm.Matrix,0,0);
matrixsm:=nil;
SetLength(R,0,0);
R:=nil;

end;

function Tgraph.IsPath(S,F:TV):boolean;
begin
if SearchReachMatrix[num(s),num(f)]=1 then
  result:=true
else
  result:=false;
end;


constructor TGraph.Invert(G: tgraph);
var i, j: integer;
begin
  create;
  Orgraph:=false;
  setlength(v, length(g.v));
  for i := 1 to high(g.V) do begin
    v[i]:=g.V[i];
    for j := 1 to i-1 do
      if (g.GetE(g.V[i], g.V[j]) = nil) then
        Create(g.V[j], g.V[i]);
  end;
end;

function Tgraph.SearchMaxStreamAndRazrez(var Razr:tgraph;s,t:tv;var MaxStream:integer):shortint;
type TP = record
  ist:integer; //вершнина из которой идет поток
  stream:integer;//поток, к-ый можно передать по этой дуге (из ist в текущ)
end;
var LG:boolean;
  p:array of TP;//массив меток
  i,j:integer;
  c:array of array of integer;//матрица пропускных способностей
  F:array of array of integer;//матрица потоков

//расстановка меток
procedure Mark;
var M: array of boolean; //непросмотренные вершины
  L,i:integer;
begin
SetLength(m,length(g.V));
for i := 1 to high(m) do
  m[i]:=true;
p[num(s)].ist:=num(s);
p[num(s)].stream:=MaxInt;
L:=num(s);

while (p[num(t)].ist=0) and lg do
begin
  for i := 1 to high(g.V) do //поиск непомеченной вершины
    if (p[i].ist=0) and ((c[L,i]<>0) or (c[i,l]<>0)) then
      if f[L,i]<c[L,i] then  //если дуга прямая
      begin
        p[i].ist:=L;
        if p[L].stream<c[L,i]-F[l,i] then
          p[i].stream:=p[L].stream
        else
          p[i].stream:=c[L,i]-F[L,i];
      end
      else //если дуга обратная
      if f[i,L]>0 then
      begin
        p[i].ist:=-L;
        if p[l].stream<F[i,L] then
          p[i].stream:=p[L].stream
        else
          p[i].stream:=F[i,L];
      end;
  m[L] := false;  //вершина L просмотрена
  L := 1;
  //ищем помеченную и непросмотренную вершину
  repeat
    inc(L);
  until (L>high(G.V)) or ((p[L].ist<>0) and (m[L] = true));
  if L>high(g.V) then
    lg := false;
end;
end;


//изменение потока по дугам найденной цепочки
Procedure Stream(q:integer);
begin
//определяем прямая ли дуга (-номер вершины - обратная)
if p[q].ist>0 then
  F[p[q].ist,q]:=f[p[q].ist,q]+p[num(t)].stream
else
   F[q,abs(p[q].ist)]:=F[q,abs(p[q].ist)]-p[num(t)].stream;
if abs(p[q].ist)<>num(s) then  //если не источник то идем к предыд вершине цепочки
begin
  q := abs(p[q].ist);
  stream(q);
end;
end;


begin
//исключения
if not web then
begin
  result:=-1;
  exit;
end;

if IsPath(s,t)=false then
begin
  result:=-2;
  exit;
end;

setlength(p,length(g.V));
SetLength(c,length(g.V),length(g.V));
SetLength(f,length(g.V),length(g.V));
for i := 1 to high(g.V) do
  for j := 1 to high(g.V) do
    if gete(g.V[i],g.V[j])<>nil then
      c[i,j]:=gete(g.V[i],g.V[j]).ves
    else
      c[i,j]:=0;
{for i := 1 to high(g.E) do
  g.E[i].potok:=0; }
lg:=true;
while lg do
begin
  for i := 1 to high(p) do
  begin
    p[i].ist:=0;
    p[i].stream:=0;
  end;

  mark;
  if lg then
    stream(num(t));
end;

for i := 1 to high(g.v) do
  for j := 1 to high(g.V) do
    if GetE(g.V[i],g.V[j]) <> nil then
      GetE(g.V[i],g.V[j]).potok:=f[i,j];
MaxStream:=0;
for i := 1 to high(GetIncE2(t,-1)) do
  MaxStream:=MaxStream+GetIncE2(t,-1)[i].potok;

//поиск разрезов
razr:=tgraph.Create;
for i := 1 to high(g.e) do
  if ((p[num(g.E[i].p1)].ist<>0) and (p[num(g.E[i].p2)].ist=0)) or ((p[num(g.E[i].p2)].ist<>0) and (p[num(g.E[i].p1)].ist=0)) then
    razr.Add(g.E[i]);

SetLength(f,0,0);
SetLength(c,0,0);
SetLength(p,0);
f:=nil;
c:=nil;
p:=nil;
result:=1;

end;

function TGraph.Coloring(var ChromaticNumber: integer): shortint;
var MaxNezav:TArrG;
  M: TBoolMatrix;//матрица максимально независимых множеств (столбец - макс незав мн-во, строка вершина)
  NotCover : array of boolean;//массив непокрытых строк м-цы M (непокрашенных вершин)
  CountNotCover:integer;//число непокрашенных вершин
  i,j:integer;
  NMax,max:integer;//номер незав мно-ва, покрывающего наиб число непокрашенных вершин и само это число
  temp:integer;//сколько непокрытых вершин покрывает текущее незав мн-во
  color:tcolor;
  arrcolors: array of tcolor;
begin

if Orgraph then
begin
  result := -1;
  exit;
end;
randomize;
MaxNezav:=Nezav(g);
SetLength(m,length(g.V),length(MaxNezav));
SetLength(NotCover,length(g.V));
CountNotCover:=high(g.V);
Nmax:=1;
SetLength(arrcolors,1);
ChromaticNumber:=0;
for i := 1 to high(NotCover) do
  NotCover[i]:=true;

for i := 1 to high(g.V) do
  for j := 1 to high(MaxNezav) do
    if MaxNezav[j].ExistV(g.V[i]) then
      m[i,j]:=1;


while CountNotCover>0 do
begin
  //поиск Max
  max:=0;
  for i := 1 to high(maxnezav) do
  begin
    temp:=0;
    for j := 1 to high(NotCover) do
      if (m[j,i] = 1) and (NotCover[j] = true) then
        inc(temp);
    if temp>max then
    begin
      max:=temp;
      nmax:=i;
    end;
  end;
  color:=rgb(random(256),random(256),random(256));
  i:=1;
  while i<=high(arrcolors) do
  begin
   if (abs(GetRValue(arrcolors[i]-color))<255/high(g.V)) or (abs(GetBValue(arrcolors[i]-color))<255/high(g.V)) or (abs(GetGValue(arrcolors[i]-color))<255/high(g.V)) then
    begin
      color:=rgb(random(256),random(256),random(256));
      i:=0;
    end;
    inc(i);
  end;




  SetLength(arrcolors,length(arrcolors)+1);
  arrcolors[high(arrcolors)]:=color;
  //color:=rgb(random(round(255/high(g.V)))-ChromaticNumber*round(255/high(g.V)),255-random(round(255/high(g.V)))-ChromaticNumber*round(255/high(g.V)),255-random(round(255/high(g.V)))-ChromaticNumber*round(255/high(g.V)));
  //showmessage(inttostr(255-random(round(255/high(g.V)))-ChromaticNumber*round(255/high(g.V))));
  //color:=rgb(255-random(round(255/high(g.V)))+ChromaticNumber*10,255-random(round(255/high(g.V)))+ChromaticNumber*10,255-random(round(255/high(g.V)))+ChromaticNumber*10);

  for i := 1 to high(g.V) do
    if (MaxNezav[nmax].ExistV(g.V[i])) and (notcover[i]) then
    begin
      g.V[i].color:=color; //nmax;//??
      NotCover[i] := false;
      dec(CountNotCover);
    end;
  inc(ChromaticNumber);


end;
setlength(arrcolors,0);
arrcolors:=nil;
SetLength(NotCover,0);
NotCover:=nil;
SetLength(m,0,0);
m:=nil;
result:=1;
end;


//function TGraph.Coloring(var ChromaticNumber: integer): shortint;
//var MaxNezav:TArrG;
//  M: TBoolMatrix;//матрица максимально независимых множеств (столбец - макс незав мн-во, строка вершина)
//  NotCover : array of boolean;//массив непокрытых строк м-цы M (непокрашенных вершин)
//  CountNotCover:integer;//число непокрашенных вершин
//  i,j:integer;
//  NMax,max:integer;//номер незав мно-ва, покрывающего наиб число непокрашенных вершин и само это число
//  temp:integer;//сколько непокрытых вершин покрывает текущее незав мн-во
//  color:tcolor;
// // flag:boolean;  //покрасили ли на этом шаге вершину
//begin
//
//if Orgraph then
//begin
//  result := -1;
//  exit;
//end;
//randomize;
//MaxNezav:=Nezav(g);
//SetLength(m,length(g.V),length(MaxNezav));
//SetLength(NotCover,length(g.V));
//CountNotCover:=high(g.V);
//Nmax:=1;
////max:=0;
//ChromaticNumber:=0;
//for i := 1 to high(NotCover) do
//  NotCover[i]:=true;
//
//for i := 1 to high(g.V) do
//  for j := 1 to high(MaxNezav) do
//    if MaxNezav[j].ExistV(g.V[i]) then
//      m[i,j]:=1;
//
//
//while CountNotCover>0 do
//begin
//  //поиск Max
//  max:=0;
//  for i := 1 to high(maxnezav) do
//  begin
//    temp:=0;
//    for j := 1 to high(NotCover) do
//      if (m[j,i] = 1) and (NotCover[j] = true) then
//        inc(temp);
//    if temp>max then
//    begin
//      max:=temp;
//      nmax:=i;
//    end;
//  end;
//  //flag:=false;
//  color:=rgb(random(256),random(256),random(256));
//  for i := 1 to high(g.V) do
//    if (MaxNezav[nmax].ExistV(g.V[i])) and (notcover[i]) then
//    begin
//      //flag:=true;
//      g.V[i].color:=color; //nmax;//??
//      NotCover[i] := false;
//      dec(CountNotCover);
//    end;
//    //if max>0 then
//      inc(ChromaticNumber);
//
//
//end;
//
//SetLength(NotCover,0);
//NotCover:=nil;
//SetLength(m,0,0);
//m:=nil;
//result:=1;
//end;

procedure Tgraph.SaveImage(filename: string; g: tgraph = nil);
var canv:TPicture;
jpeg: TJPEGImage;
begin
  jpeg:=TJPEGImage.Create;
  canv:=TPicture.Create;
  try
    canv.Bitmap.Width:= col.wi;
    canv.bitmap.Height:=col.he;
    draw(canv.Bitmap.Canvas);
    if g<> nil then g.draw(canv.Bitmap.Canvas, true);
    jpeg.Assign(canv.Graphic);
    jpeg.savetofile(FileName);
  finally
    canv.free;
    jpeg.Free;
  end;
end;


constructor TGraph.CreatewithInc(filename: string);
var graphfile: Text;
x, y,i, j, ves: integer;
arr: array of array of integer;
ver: TV;
begin
  try
    AssignFile(graphfile,filename);
		reset(graphfile);
    Read(graphfile, x, y);
    setlength(arr, x+1, y+1);
    for j := 1 to y do
      for i  := 1 to x do
        Read(graphfile, arr[i][j]);
    create;
    for i := 1 to y do begin
      Create(round(cos(2*PI*i/x)*100+150), round(sin(2*PI*i/x)*100+150));
    end;
    for i := 1 to x do begin
      ves:=0;
      for j := 1 to y do
        if (arr[i][j]<> 0) then
          if ves = 0 then
            ves:=j
          else begin
            if (arr[i][ves] > 0) then
              create(v[ves], v[j])
            else
              create(v[j], v[ves]);
            break;
          end;
    end;
  except
  end;
end;

constructor TGraph.CreatewithSm(filename: string);
var graphfile: Text;
x,i, j, ves: integer;
arr: array of array of integer;
ver: TV;
begin
  try
    AssignFile(graphfile,filename);
		reset(graphfile);
    Read(graphfile, x);
    setlength(arr, x+1, x+1);
    for j := 1 to x do
      for i  := 1 to x do
        Read(graphfile, arr[i][j]);
    create;
    for i := 1 to x do begin
      Create(round(cos(2*PI*i/x)*100+150), round(sin(2*PI*i/x)*100+150));
    end;

    for i := 1 to x do begin
      ves:=0;
      for j := 1 to x do
        if (i<>j) then
          if (arr[i][j] = 1) then
            create(v[i], v[j])
          else if (arr[i][j] = 1) then
              create(v[j], v[i])
    end;
  except
  end;
end;


end.


Соседние файлы в папке Программа для построения и анализа графов