Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

АиПА / include / algraph

.h
Скачиваний:
7
Добавлен:
07.02.2016
Размер:
59.26 Кб
Скачать
/*----------------------------------------------------------------------------*/
/* Пакет VP/C++. Модуль Algraph. Вер. 01.2004.                                */
/* Пинчук В.П., ЗНТУ, Украина, vpinchuk@zntu.edu.ua                           */
/* тел.(0612)636800,698414                                                    */
/*----------------------------------------------------------------------------*/
#include <syst.h>
typedef  unsigned short  vert;
/* Классы --------------------------------------------------------------------*/
  class matad;
  class graph
{ public:
  int   nv;										// число вершин
  vert  *p;                            // вектор степеней вершин
  vert **r;                            // таблица связей
  graph() { nv=0; p=0; r=0; }          // конструктор без параметров
  graph(const graph&);						// конструктор копирования
  graph(const matad&);                 // конструктор преобразования
  graph(int);                          // конструктор безреберного графа
 ~graph() { cnv(); }							// деструктор
  graph& operator=(const graph&);		// динамич. присваивание
  graph& operator=(const matad&);      // присваивание с преобразованием
  graph& operator=(int);					// создать безреберный граф с n верш.
  graph& operator<<(FILE*);  				// Ввод из текстового файла
  graph& operator>>(FILE*);				// Вывод в текстовый файл
  int    operator==(int);					// явл. ли граф безреберным с n верш.
  int   write_r(FILE*);		// запись графа в r-файл, возвр. число ребер графа
  int   read_r(FILE*);		// чтение графа из r-файла, возвр. число ребер
  void  write(FILE*);		// Вывод в текстовый файл или на экран
  int   read(FILE*);			// Ввод из текстового файла, возвр. form-фактор
  void  cnv();					// свернуть graph-объект
  void  rgl();             // упорядочить номера вершин в строках таблицы связей
  int   size();				// размер graph-объекта в байтах
  int   nrib() const; 		// число ребер
  int   form() const; 		// форм-фактор графа
  int   ver();
};
  class matad
{ public:
  int   nv;
  byte **s;
  matad(){nv=0; s=0;}
  matad(const matad&);
  matad(const graph&);
  matad(int);
 ~matad();
  matad& operator=(const matad&);
  matad& operator=(const graph&);
  matad& operator=(int);
  void write(FILE*);			// Вывод в текстовый файл или на экран
  int  read(FILE*);			// Ввод из текстового файла, возвр. form-фактор
  int  size();             // размер объекта в байтах
  int  form() const;			// форм-фактор графа
  int  nrib();					// число ребер
};
  class pinv
{ public:
  int  nv;
  vert* v;
  pinv() { nv=0; v=0; }
  pinv(const pinv&);
 ~pinv() { if (nv) { delete[] v; v=0; nv=0; } }
  pinv& operator=(const pinv&);
  pinv& operator=(const graph&);
  pinv& operator=(int);
  void write(FILE*);			// Вывод в текстовый файл или на экран
  void read(FILE*);			// Ввод из текстового файла
};
  template <class type>
  class graph_v: public graph
{ public:
  type* wv;
};
  template <class type>
  class graph_r: public graph
{ public:
  type** wr;
  graph_r(const graph&);
  graph_r(const graph_r<type>&);
  void wr_max(int& im, int& jm);
  void wr_clear();
};
  template <class vtype, class rtype>
  class graph_vr: public graph_v<vtype>, public graph_r<rtype>
{
};
  template <int dim>
  class imgraph: public graph
{ public:
};
/* Внешние перегруженные операции --------------------------------------------*/
int     operator==(const graph&, const graph&);	// одинаковы ли таблицы связей
int     operator==(const matad&, const matad&);	// равны ли матрицы смежности
int     operator==(const pinv&, const pinv&);	// равны ли pi-инварианты
graph   operator+(const graph&, const graph&);	// объединение графов
graph   operator~(const graph&);				      // получить дополнительный граф
matad   operator~(const matad&);			 // получить матрицу смеж. дополн. графа
/* Функции и процедуры -------------------------------------------------------*/
  char* about_algraph();  						// информация о разработчике
  void  add_edge(graph& g, int i, int k);	// добавить дугу
  void  add_r(graph& g, int i, int k);		// добавить ребро (пару встречных дуг)
  void  add_v(graph& g);			 			// добавить изолир. вершину
  void  add_vc(graph& g);			// добавить вершину, смежную ко всем остальным
  int   bic_graph(const graph& g, word* bic); // преобразование graph -> bic, возвр.
  														// значение - длина бикода (к-во слов)
  int   bic_mat(const matad& M, word* bic);	 // преобразование matad -> bic, возвр.
  														// значение - длина бикода (к-во слов)
  int   biclen(int nv);							// длина бикода (к-во слов типа word)
  int   cliq(const graph& g, vert* e);		// найти плотность графа и клику
  int   cmp(const pinv& a, const pinv& b);	 // сравнение инвариантов
  int   cmpl(const graph& g, int i, int k);	 // сравнить две строки таблицы связей
  graph complete(int n);                  // получить полный граф на n вершин
  void  del_iv(graph& g);						// удалить все изолированные вершины
  void  del_r(graph& g, int i, int k);		// удалить ребро или пару встреч. дуг
  void  del_v(graph& g, int k);				// удалить вершину
  int   dens(graph, int=0);  					// получить плотность графа (NB-метод)
  int   densi(const graph& g); 				// получить плотность графа (clic-метод)
  int   dens_lo(const graph& g);				// получить нижнюю оценку плотности
  int   diameter(const graph& g); 			// получить диаметр графа
  int   dist(const graph& g, int i, int m); 	 // расстояние между вершинами
  graph dlv(const graph& g, int k);	 		// получить граф с удаленной вершиной
  graph double_o_graph(int n);				// получить граф типа "двойное кольцо"
  int   excenter(const graph& g,int i); 	// получить эксцентриситет вершины
  graph fatring(int nv, int c);				// получить граф типа fatring
  int   findcycl(const graph& g, int j, int L, vert* e);
  														// найти цикл, который проходит через
                                          // вершину j и имеет длину L, результат -
                                          // в массиве e
  graph graph_bic(int nv, word* bic); 		// преобразование bic -> graph
  int   gt_r(FILE* in, FILE* out);			// конвертирование файлов: gt -> r
  int   hamilt_c(const graph& g, int* e);	// найти гамильтонов цикл
  ulong hamilt_n(const graph& g);	 		// получить число гамильтоновых циклов
  graph hamming(int n, int d);				// получить граф Хэмминга
  graph hcube(int m);							// получить гиперкуб размерности m
  void  hread(FILE* f, word& nv, word& nr, ulong& Ng, ulong& KS);
  														// прочитать заголовок r-файла
  void  hwrite(FILE* f, word nv, word nr, ulong Ng, ulong KS);
  														// записать заголовок r-файла
  int   isblock(const graph& g);				// явл. ли граф блоком
  int   iscomplete(const graph& g);			// явл. ли граф полным
  int   isconn(const graph& g);				// явл. ли граф связным
  int   isdual(const graph& g);				// явл. ли граф двудольным
  int   isempty(const graph& g);				// явл. ли граф пустым
  int   iseuler(const graph& g);				// явл. ли граф эйлеровым
  int   ishamilt(const graph& g); 			// явл. ли граф гамильтоновым
  int   isisos(const graph& a, const graph& b, int* p);
  													 	// явл. ли подстановка p изоморфной
  int   iso(const graph& A, const graph& B);	 // явл. ли графы изоморфными
  int   isos(const graph& A, const graph& B, int* p);
  														// получить изоморфную подстановку
  int   isregular(const graph& g);			// явл. ли граф регулярным
  int   isucycl(const graph& g);				// явл. ли граф ациклическим
  int   isulamequ(const graph& A, const graph& B);
  														// явл. ли графы Улам-эквивалентными
  int   isnonbridge(const graph& g); 		// явл. ли граф графом без мостов
  graph johnson(int n, int w, int d);		// получить граф Джонсона
  graph join(const graph& A, const graph& B); // получить слабое соединение графов
  graph joinc(const graph& A, const graph& B);// получить сильное соединение графов
  graph k_line(int n, int k);					// получить граф типа k-line
  graph k_ring(int n, int k);					// получить граф типа k-ring
  graph keller(int n);							// получить граф Келлера
  graph line(int n);                      // получить line-граф
  matad mat_bic(int nv, word* bic);			// преобразование bic -> matad
  graph modmul(const graph& A, const graph& B);// получить модульное произведение
  int   n_orbit(const graph& G);				// к-во орбит группы автоморфизмов
  ulong naut(const graph& A);					// получить Naut(g)
  graph neib(const graph& g, int k); 		// получить подграф ближ. соседей
  ulong nisos(const graph& A, const graph& B);// получить к-во изоморф. подстановок
  int   nrib(const graph& g);					// получить число ребер
  ulong ntriangls(const graph& g);			// получить число треугольников
  graph o_graph(int n);							// получить О-граф
  void  one_two(int k, int& i, int& j); // по заданному номеру бита бинарного кода k
										// находятся индексы соотв. эл-та матрицы смежности i,j
  void  print(const matad& M);
  void  print(const pinv& P);
  graph r_inters(const graph& A, const graph& B);
  														// получить реберное пересечение
  ulong r_gt(FILE* in, FILE* out);			// конвертирование файлов: r -> gt
  graph r_union(const graph& A, const graph& B);
  														// получить реберное объединение
  int   radius(const graph& g);				// получить радиус графа
  graph randgraph(int n, int r);				// получить случайный граф
  graph randgraph(int nv, float p);			// получить случайный граф
  int   read_bic(FILE* in, int Nw, word* bic); // прочитать из r-файла бинарный
  										// код длиной Nw и занести в массив bic,
                              // возвращается число ед. бикода (число ребер)
  graph renum(const graph& g);// получить граф путем случ. перенумерации вершин
  int   rver(FILE* in);  		// Проверка r-файла, функция возвращает:
										// 0, если все в порядке,
										// 1, если неправильная контр.сумма,
										// 2, если число ребер не соответствует объявл. в заголовке,
                              // 3, если в заголовке r-файла указано нулевое число графов
                              // 4, если число вершин, объявл. в заголовке, > 1024
                              // 5, если число графов в r-файле не соотвует заголовку
  graph sanchis(int n, int r, int d);		// получить граф Санчиса
  ulong sigma(const graph& g);// получить свертку first-инварианта для графа g
  graph star(int n);				// получить граф типа звезда
  int   streg(const graph& g, int& m0, int& m1);// явл. ли граф сильнорегулярным
  int   two_one(int i, int j); // по индексам i,j элемента матрицы смежности
										// определяется номер бита бинарного кода
  int   ver(const graph& g);	// проверить таблицу связей графа
  int   verification_r(FILE* f); // проверка r-файла
  graph wheel(int n);			// получить граф типа колесо
  void  write_bic(FILE* out, int Nw, word* bic); // записать в r-файл бинарный
  																 // код длиной Nw из массива bic
/* Реализация. Классы --------------------------------------------------------*/
/* Class graph ---------------------------------------------------------------*/
  graph::graph(const graph& g)
{ vert i,j,k;
  nv=g.nv; if (nv==0) { p=0; r=0; return; }
  p=new vert[nv];
  r=new vert*[nv];
  for (i=0;i<nv;i++)
      { k=p[i]=g.p[i];
        r[i]=new vert[k];
	for (j=0;j<k;j++) r[i][j]=g.r[i][j]; }
}
  graph::graph(const matad& M)
{ vert i,j,k; byte mr;
  nv=M.nv; if (nv==0) { p=0; r=0; return; }
  p=new vert[nv];
  r=new vert*[nv];
  for (i=0;i<nv;i++)
    { k=0;
      for (j=0;j<nv;j++) k+=M.s[i][j];
	   p[i]=k;
      r[i]=new vert[k];
      k=0;
      for (j=0;j<nv;j++) { mr=M.s[i][j];
                           while (mr>0) { r[i][k++]=j; mr--; }
                         }
    }
}
  graph::graph(int N)
{ nv=N; if (nv==0) { p=0; r=0; return; }
  p=new vert[nv];
  r=new vert*[nv];
  for (vert i=0;i<nv;i++) { p[i]=0; r[i]=0; }
}
  graph& graph::operator=(const graph& g)
{ if (this==&g) return *this;
  cnv(); if (g.nv==0) return *this;
  vert i,j;
  nv=g.nv;
  p=new vert[nv];
  r=new vert*[nv];
  for (i=0;i<nv;i++)
      { p[i]=g.p[i];
        r[i]=new vert[p[i]];
	     for (j=0;j<p[i];j++) r[i][j]=g.r[i][j]; }
  return *this;
}
  graph& graph::operator=(const matad& M)
{ cnv(); if (M.nv==0) return *this;
  vert i,j,k; byte mr;
  nv=M.nv;
  p=new vert[nv];
  r=new vert*[nv];
  for (i=0;i<nv;i++)
    { k=0;
      for (j=0;j<nv;j++) k+=M.s[i][j];
      p[i]=k;
      r[i]=new vert[k];
      k=0;
      for (j=0;j<nv;j++) { mr=M.s[i][j];
                           while (mr>0) { r[i][k++]=j; mr--; }
                         }
    }
  return *this;
}
  graph& graph::operator=(int N)
{ cnv(); if (N==0) return *this;
  nv=N;
  p=new vert[nv];
  r=new vert*[nv];
  for (vert i=0;i<nv;i++) { p[i]=0; r[i]=0; }
  return *this;
}
  graph& graph::operator<<(FILE* f)
{ read(f); return *this;
}
  graph& graph::operator>>(FILE* f)
{ write(f);
  return *this;
}
  int graph::operator==(int N)
{ int i, r=0;
  for (i=0;i<nv;i++) r+=p[i];
  if ( nv==N && r==0 ) return 1; else return 0;
}
  graph  operator~(const graph& g)
{ matad M=g;
  int i,j,nv=M.nv;
  for (i=0;i<nv;i++)
    for (j=i+1;j<nv;j++)
      { if (M.s[i][j]) { M.s[i][j]=0; M.s[j][i]=0; }
        else           { M.s[i][j]=1; M.s[j][i]=1; } }
  graph x=M;
  return x;
}
  void graph::cnv()
{ if (nv) { for (int i=0;i<nv;i++) delete[] r[i];
	         delete[] r; delete[] p; nv=0; }
  p=0; r=0;
}
  int graph::size()
{ int i, sv = sizeof(vert), sz=0;
  for (i=0;i<nv;i++) sz+=p[i]*sv;
  sz+= nv*4+12;
  return sz;
}
  int graph::form() const
{ return matad(*this).form();
}
  graph operator+(const graph& A, const graph& B)
{ int nv=A.nv+B.nv;
  graph g; g=nv;
  int i,ii,j;
  for (i=0;i<A.nv;i++) { g.p[i]=A.p[i];
                         g.r[i]= new vert[g.p[i]];
                         for (j=0;j<g.p[i];j++) g.r[i][j]=A.r[i][j]; }
  for (i=0;i<B.nv;i++) { ii=i+A.nv;
  								 g.p[ii]=B.p[i];
                         g.r[ii]= new vert[g.p[ii]];
                         for (j=0;j<g.p[ii];j++) g.r[ii][j]=(vert)(B.r[i][j]+A.nv); }
  return g;
}
  int operator==(const graph& A, const graph& B)
{ int i,j;
  if (A.nv!=B.nv) return 0;
  for (i=0;i<A.nv;i++) if (A.p[i]!=B.p[i]) return 0;
  for (i=0;i<A.nv;i++)
    for (j=0;j<A.p[i];j++) if (A.r[i][j]!=B.r[i][j]) return 0;
  return 1;
}
  int graph::read_r(FILE* in)
{ if (nv==0) { printr("graph::read_r(FILE*): ОШИБКА: чтение в пустой граф\n"); }
  int nr, Nw= biclen(nv);
  word* bic= new word[Nw];
  nr=read_bic(in,Nw,bic);
  int i,k,r, J=0;
  word t=0;
  matad M(nv);
  for (i=1;i<nv;i++)
    for (k=0;k<i;k++)
      { if (t==0) t=0x8000;
        r=J/16;
        if (t & bic[r]) M.s[i][k]=M.s[k][i]=1;
        t>>=1; J++;
      }
  delete[] bic;
  *this=M;
  return nr;
}
  int graph::write_r(FILE* out)
{ int i,k,r,nr=0, J=0, Nw= biclen(nv);
  word t=0;
  word* bic= new word[Nw]; for (i=0;i<Nw;i++) bic[i]=0;
  matad M(*this);
  for (i=1;i<nv;i++)
    for (k=0;k<i;k++) { if (t==0) t=0x8000;
                        r=J/16;
                        if (M.s[i][k]) { bic[r] |= t; nr++; }
                        t>>=1; J++;
                      }
  write_bic(out,Nw,bic);
  delete[] bic;
  return nr;
}
  void graph::rgl()
{ int i,j,k,l;
  vert q, *s;
  for (i=0;i<nv;i++)
    { s=r[i];
      for (j=0;j<p[i];j++)
	     { q=s[j]; l=j;
	       for (k=j+1;k<p[i];k++) if (s[k]<q) { q=s[k]; l=k; }
          swp(s[j],s[l]);
        }
    }
}
  void  graph::write(FILE* f = stdout)
{ char *frm,
       *frm1="%1d ",
       *frm2="%2d ",
       *frm3="%3d ";
  if (nv<10)       frm=frm1;
  else if (nv<100) frm=frm2;
  else             frm=frm3;
  int i,j;
  fprintf(f,"%3d \n",nv);
  for (i=0;i<nv;i++)
      { fprintf(f,"%3d  %3d    ", i+1, p[i]);
        for (j=0;j<p[i];j++) fprintf(f,frm,r[i][j]+1);
        fprintf(f,"\n");
      }
}
  int graph::read(FILE* f)
{ int i,j,k,v,R;
  cnv();
  fscanf(f,"%d",&nv);
  if (nv>65535) { nv=0; goto mmm; }
  p=new vert[nv];
  r=new vert*[nv]; for (i=0;i<nv;i++) r[i]=NULL;
  for (i=0;i<nv;i++)
    { fscanf(f,"%d %d",&v,&k);
      if (v!=i+1) goto mmm;
      p[i]=(vert)k;
      r[i]=new vert[k];
      for (j=0;j<k;j++) { fscanf(f,"%d",&R); r[i][j]=(vert)(R-1); }
    }
  if (ver()) return form();
  mmm:
  *this=0;
  printr("graph::read(f): ОШИБКА: неправильный формат gt-таблицы\n");
  return 0;
}
  int graph::nrib() const
{ return matad(*this).nrib();
}
  int graph::ver()
{ rgl();
  int i,j, q=1;
  if (nv<0) q=0;
  for (i=0;i<nv;i++)
    for (j=0;j<p[i];j++) if (r[i][j]>=nv) return 0;
  return q;
}
/* Class matad ---------------------------------------------------------------*/
  matad::matad(const matad& M)
{ nv=M.nv;
  if (nv==0) { s=0; return; }
  int i,j;
  s=new byte*[nv];
  for (i=0;i<nv;i++)
      { s[i]=new byte[nv];
        for (j=0;j<nv;j++) s[i][j]=M.s[i][j]; }
}
  matad::matad(const graph& g)
{ nv=g.nv;
  if (nv==0) { s=0; return; }
  int i,j,k;
  s=new byte*[nv];
  for (i=0;i<nv;i++)
      { s[i]= new byte[nv];
	     for (k=0;k<nv;k++) s[i][k]=0;
	     for (k=0;k<g.p[i];k++) { j=g.r[i][k]; s[i][j]++; }
      }
}
  matad::matad(int N)
{ int i,j;
  nv=N; if (nv==0) { s=0; return; }
  s=new byte*[nv];
  for (i=0;i<nv;i++) s[i]=new byte[nv];
  for (i=0;i<nv;i++) for (j=0;j<nv;j++) s[i][j]=0;
}
  matad::~matad()
{ if (nv) { for (int i=0;i<nv;i++) delete[] s[i];
            delete[] s;
          }
}
  matad& matad::operator=(const matad& M)
{ if (this==&M) return *this;
  int i,j;
  for (i=0;i<nv;i++) delete[] s[i]; delete[] s; s=0;
  nv=M.nv; if (nv==0) return *this;
  s=new byte*[nv];
  for (i=0;i<nv;i++)
      { s[i]=new byte[nv];
        for (j=0;j<nv;j++) s[i][j]=M.s[i][j]; }
  return *this;
}
  matad& matad::operator=(const graph& g)
{ int i,j,k;
  if (nv) { for (i=0;i<nv;i++) delete[] s[i]; delete[] s; s=0; }
  nv=g.nv;
  if (nv==0) return *this;
  s=new byte*[nv];
  for (i=0;i<nv;i++)
      { s[i]=new byte[nv];
        for (j=0;j<nv;j++) s[i][j]=0;
        for (j=0;j<g.p[i];j++) { k=g.r[i][j]; s[i][k]++; }
      }
  return *this;
}
  matad& matad::operator=(int N)
{ int i,j;
  if (nv) { for (i=0;i<nv;i++) delete[] s[i]; delete[] s; s=0; }
  nv=N; if (nv==0) return *this;
  s=new byte*[nv];
  for (i=0;i<nv;i++) s[i]=new byte[nv];
  for (i=0;i<nv;i++) for (j=0;j<nv;j++) s[i][j]=0;
  return *this;
}
  int matad::size()
{ int sz= nv*nv+nv*4+8;
  return sz;
}
  int operator==(const matad& Ma, const matad& Mb)
{ if (Ma.nv!=Mb.nv) return 0;
  int i,j;
  for (i=0;i<Ma.nv;i++)
    for (j=0;j<Ma.nv;j++) if (Ma.s[i][j]!=Mb.s[i][j]) return 0;
  return 1;
}
  matad operator~(const matad& M)
{ int i,j,nv=M.nv;
  matad A(nv);
  for (i=0;i<nv;i++)
    for (j=i+1;j<nv;j++)
      { if (M.s[i][j]) { A.s[i][j]=0; A.s[j][i]=0; }
        else           { A.s[i][j]=1; A.s[j][i]=1; } }
  return A;
}
  int matad::form() const
{ int i,j,frm=0;
  for (i=1;i<nv;i++)
    { if (frm==1) break;
      for (j=0;j<i;j++) if (s[i][j]!=s[j][i]) { frm|=0x1; break; }
    }
  for (i=0;i<nv;i++) if (s[i][i]>0) { frm|=0x2; break; }
  for (i=0;i<nv;i++)
    { if (frm & 0x4) break;
      for (j=0;j<nv;j++) if (s[i][j]>1) { frm|=0x4; break; }
    }
  return frm;
}
  void  matad::write(FILE* out = stdout)
{ int i,j, m=0;
  char *frm,
       *frm1="%1d ",
       *frm2="%2d ",
       *frm3="%3d ";
  for (i=0;i<nv;i++) for (j=0;j<nv;j++) if (m<s[i][j]) m=s[i][j];
  if (m<10)       frm=frm1;
  else if (m<100) frm=frm2;
  else            frm=frm3;
  fprintf(out,"%3d \n",nv);
  for (i=0;i<nv;i++)
    { fprintf(out,"%3d   ",i+1);
      for (j=0;j<nv;j++) fprintf(out,frm,s[i][j]);
      fprintf(out,"\n");
    }
}
  int matad::read(FILE* in)
{ int i,j,k;
  *this = 0;
  fscanf(in,"%d",&nv);
  s=new byte*[nv];
  for (i=0;i<nv;i++) s[i]=new byte[nv];
  for (i=0;i<nv;i++)
    { fscanf(in,"%d",&k);
      if (k!=i+1) { printr("ОШИБКА: matad::read(in): неверный формат файла\n");
                    exit(0);
                  }
      for (j=0;j<nv;j++) { fscanf(in,"%d",&k); s[i][j]=(byte)k; }
    }
  return form();
}
  int matad::nrib()
{ int i,j,nr=0;
  for (i=0;i<nv;i++)
    for (j=0;j<=i;j++) nr+=s[i][j];
  if ((form() & 0x1) == 0) return nr;
  for (i=0;i<nv-1;i++)
    for (j=i+1;j<nv;j++) nr+=s[i][j];
  return nr;
}
/* Class pinv ----------------------------------------------------------------*/
  pinv::pinv(const pinv& P)
{ nv=P.nv;
  v=new vert[nv];
  for (int i=0;i<nv;i++) v[i]=P.v[i];
}
  pinv& pinv::operator=(int N)
{ errhalt(N,"pinv::operator=(int): abnormal parameter int: must be zero only");
  if (nv) { delete[] v; v=0; nv=0; }
  return *this;
}
  pinv& pinv::operator=(const pinv& P)
{ if (nv)  delete[] v;
  nv=P.nv;
  v=new vert[nv];
  for (int i=0;i<nv;i++) v[i]=P.v[i];
  return *this;
}
  pinv& pinv::operator=(const graph& g)
{ if (nv) delete v;
  int i,j,jm; nv=g.nv;
  v=new vert[nv];
  for (i=0;i<nv;i++) v[i]=g.p[i];
  for (i=0;i<nv-1;i++)
    { jm=i;
	   for (j=i+1;j<nv;j++)  if (v[jm]<v[j]) jm=j;
	   swp(v[i],v[jm]); }
  return *this;
}
  int operator==(const pinv& a, const pinv& b)
{ if (a.nv != b.nv) return 0;
  for (int i=0;i<a.nv;i++) if (a.v[i] != b.v[i]) return 0;
  return 1;
}
  void pinv::write(FILE* f= stdout)
{ char *frm,
       *frm1="%1d ",
       *frm2="%2d ",
       *frm3="%3d ";
  if (nv<10)       frm=frm1;
  else if (nv<100) frm=frm2;
  else             frm=frm3;
  fprintf(f,"%3d\n",nv);
  for (int i=0;i<nv;i++) fprintf(f,frm,v[i]);
  fprintf(f,"\n");
}
  void pinv::read(FILE* f)
{ if (nv) delete[] v;
  fscanf(f,"%d",&nv);
  v= new vert[nv];
  for (int i=0;i<nv;i++) fscanf(f,"%d",&v[i]);
}
/* Class graph_r -------------------------------------------------------------*/
  template <class type>
  graph_r<type>::graph_r(const graph& G): graph(G)
{ int i,j;
  wr= new type*[nv];
  for (i=0;i<nv;i++) wr[i]= new type[nv];
  for (i=0;i<nv;i++) for (j=0;j<nv;j++) wr[i][j]=0;
}
  template <class type>
  graph_r<type>::graph_r(const graph_r<type>& R): graph(R)
{ int i,j;
  wr= new type*[nv];
  for (i=0;i<nv;i++) wr[i]= new type[nv];
  for (i=0;i<nv;i++) for (j=0;j<nv;j++) wr[i][j]=R.wr[i][j];
}
  template <class type>
  void graph_r<type>::wr_max(int& im, int& jm)
{ int i,j;
  im=1; jm=0;
  for (i=1;i<nv;i++)
    for (j=0;j<i;j++) if (wr[im][jm]<wr[i][j]) { im=i; jm=j; }
}
  template <class type>
  void graph_r<type>::wr_clear()
{ for (int i=1;i<nv;i++)
    for (int j=0;j<i;j++) { wr[i][j]=0; wr[j][i]=0; }
}

/******************************************************************************/
/************************ Procedures and Functions ****************************/
  char* about_algraph()
{ return "          VP/C++ Library\n\
          ALGRAPH unit, rel. 01.2004. Computing on Graphs\n\
          V.P.Pinchuk, ZNTU, Ukraine\n\
          ph.(0612)636800, e-mail: vpinchuk@zntu.edu.ua\n\n";
}
  void  add_edge(graph& g, int i, int k)
{ matad M; M=g; M.s[i][k]++;
  g=M;
}
  void add_r(graph& g, int i, int k)
{ matad M; M=g;
  M.s[i][k]++;
  if (i!=k) M.s[k][i]++;
  g=M;
}
  void add_v(graph& g)
{ graph g1; g1=g.nv+1;
  int i,j,p;
  for (i=0;i<g.nv;i++) { p=g1.p[i]=g.p[i];
                         g1.r[i]= new vert[p];
                         for (j=0;j<p;j++) g1.r[i][j]=g.r[i][j]; }
  g=g1;
}
  void add_vc(graph& g)
{ int i,j, n=g.nv;
  matad A,B; A=g; B=n+1;
  for (i=0;i<n;i++) for (j=0;j<n;j++) B.s[i][j]=A.s[i][j];
  for (i=0;i<n;i++) { B.s[n][i]=1; B.s[i][n]=1; }
  g=B;
}
  int bic_graph(const graph& g, word* bic)
{ matad M(g);
  if (M.form()!=0) { puts("ERROR: bic_graph(g,bic): g.form()!=0"); exit(0); }
  int i,k,r, J=0,
      nv= g.nv,
      Nw= biclen(nv);
  for (i=0;i<Nw;i++) bic[i]=0;
  if (nv==0) return 0;
  word t=0;
  for (i=1;i<nv;i++)
      for (k=0;k<i;k++)
          { if (t==0) t=0x8000;
            r=J/16;
            if (M.s[i][k]) bic[r] |= t;
            t>>=1; J++;                 }
  return Nw;
}
  int bic_mat(const matad& M, word* bic)
{ if (M.form()!=0) { puts("ERROR: bic_mat(M,bic): M.form()!=0"); exit(0); }
  int i,k,r, J=0,
      nv= M.nv,
      Nw= biclen(nv);
  for (i=0;i<Nw;i++) bic[i]=0;
  if (nv==0) return 0;
  word t=0;
  for (i=1;i<nv;i++)
      for (k=0;k<i;k++)
          { if (t==0) t=0x8000;
            r=J/16;
            if (M.s[i][k]) bic[r] |= t;
            t>>=1; J++;                 }
  return Nw;
}
  int biclen(int nv)
{ return (nv*(nv-1)/2-1)/16+1;
}
  int cliq(const graph& g, vert* e)									// вариант: densi(g)
{ int d,i,j,k,m, D=1;
  int n=g.nv; if (n==0) return 0;
  matad M(g);
  if (M.form()!=0) { puts("ERROR: cliq(g,e): g.form()!=0"); exit(0); }
  vert** ns= new vert*[n];
  for (i=0;i<n;i++) ns[i]= new vert[n-i];
  vert* L= new vert[n];
  L[0]=(vert)n; for (j=0;j<n;j++) ns[0][j]=(vert)j;
  for (i=0;i<n;i++)
    { l: if (L[i]==1)
           { d=i+1;
             if (D<d) { D=d;
                        for (j=0;j<=i;j++) e[i-j]=ns[j][L[j]-1];
                      }
             lll: if (i==0) break;
             i--; L[i]--; goto l;
           }
         if (L[i]<=D-i) goto lll;
         k=0; m=L[i]-1;
         for (j=0;j<m;j++) if (M.s[ns[i][m]][ns[i][j]]) ns[i+1][k++]=ns[i][j];
         if (k==0) { L[i]--; goto l; }
         L[i+1]=(vert)k;
    }
  for (i=0;i<n;i++) delete[] ns[i];
  delete[] ns; delete[] L;
  return D;
}
  int cmp(const pinv& a, const pinv& b)
{ if (a.nv<b.nv) return -1;
  if (a.nv>b.nv) return  1;
  int i;
  for (i=0;i<a.nv;i++)
      { if (a.v[i]<b.v[i]) return -1;
        if (a.v[i]>b.v[i]) return  1; }
  return 0;
}
  int cmpl(const graph& g, int i, int k)
{ if (g.p[i]!=g.p[k]) return 0;
  int j;
  for (j=0;j<g.p[i];j++) if (g.r[i][j]!=g.r[k][j]) break;
  if (j==g.p[i]) return 1; else return 0;
}
  graph complete(int n)
{ int i,k;
  matad M(n);
  for (i=0;i<n;i++) for (k=0;k<n;k++) if (i!=k) M.s[i][k]=1;
  return graph(M);
}
  void del_iv(graph& g)
{ int i,ix,j,jx,n=0;
  matad m(g);
  for (i=0;i<g.nv;i++) if (g.p[i]) n++;
  matad mx(n);
  for (i=0,ix=0;i<g.nv;i++)
    { if (g.p[i]==0) continue;
      for (j=0,jx=0;j<g.nv;j++)
        { if (g.p[j]==0) continue;
          mx.s[ix][jx]=m.s[i][j];
          jx++;
        }
      ix++;
    }
  g=graph(mx);
}
  void del_r(graph& g, int i, int k)
{ if (i>=g.nv || k>=g.nv) return;
  matad M(g);
  if (M.s[i][k]>0 && M.s[k][i]>0) { M.s[i][k]--; M.s[k][i]--; }
  g=M;
}
  void del_v(graph& g, int k)
{ g=dlv(g,k);
}
  int dens(graph g, int lev)
{ errhalt(g.form()!=0 , "ERROR: dens(g): incorrect argument: g.form()!=0");
  static int DNS;
  byte q;
  int i,k,im,d,N;
  if (lev==0) DNS=1;
  while (1)
    { N=g.nv; if (N==0) return 0;
      for (i=0;i<g.nv;i++) if (g.p[i]==1) { del_v(g,i); i--; }
      if (g.nv<N) { d=2+lev; if (d>DNS) DNS=d; }
      N=g.nv;
      for (i=0;i<g.nv;i++) if (g.p[i]==0) { del_v(g,i); i--; }
      if (g.nv<N) { d=1+lev; if (d>DNS) DNS=d; }
      if (g.nv==0) return DNS;
      for (i=0;i<g.nv-1;i++)
	     for (k=i+1;k<g.nv;k++) if (cmpl(g,i,k)) { del_v(g,k); k--; }
      do { q=0;
           for (i=0;i<g.nv;i++)
                if (g.p[i]+lev < DNS) { del_v(g,i); q=1; }
         } while (q);
      if (g.nv==0) return DNS;
      if (nrib(g)==g.nv*(g.nv-1)/2) { d=g.nv+lev; if (d>DNS) DNS=d; return DNS; }
      im=0;
      for (i=1;i<g.nv;i++) if (g.p[im]>g.p[i]) im=i;
      dens(neib(g,im),lev+1);
      del_v(g,im);
    }
}
  int dens_lo(const graph& g)
{ errhalt(g.form()!=0 , "ERROR: dens_lo(g): incorrect argument: g.form()!=0");
  if (g.nv==0) return 0;
  int d,r;
  ulong t;
  r=g.nrib(); if (r==0) return 1;
  t=ntriangls(g);
  d= (8*r*r*r-9*t*t+3*t*sqrt(16*r*r*r+9*t*t))/(4*r*r*r-18*t*t);
  return d;
}
  int densi(const graph& g)												// вариант: cliq(g,e)
{ if (g.form()!=0) { puts("ERROR: densi(g): g.form()!=0"); exit(0); }
  int d,i,j,k,m, D=1;
  int n=g.nv; if (n==0) return 0;
  matad M(g);
  vert** ns= new vert*[n];
  for (i=0;i<n;i++) ns[i]= new vert[n-i];
  vert* L= new vert[n];
  L[0]=(vert)n; for (j=0;j<n;j++) ns[0][j]=(vert)j;
  for (i=0;i<n;i++)
    { l: if (L[i]==1)
           { d=i+1;
             if (D<d) D=d;
             ll: if (i==0) break;
             i--; L[i]--; goto l;
           }
         if (L[i]<=D-i) goto ll;
         k=0; m=L[i]-1;
         for (j=0;j<m;j++) if (M.s[ns[i][m]][ns[i][j]]) ns[i+1][k++]=ns[i][j];
         if (k==0) { L[i]--; goto l; }
         L[i+1]=(vert)k;
    }
  for (i=0;i<n;i++) delete[] ns[i];
  delete[] ns; delete[] L;
  return D;
}
  int diameter(const graph& g)
{ if (g.form()!=0) { puts("ERROR: diameter(g): g.form()!=0"); exit(0); }
  int i,ex, d=0, n=g.nv;
  for (i=0;i<n;i++) { ex=excenter(g,i); if (d<ex) d=ex; }
  return d;
}
  int dist(const graph& g, int i, int m)			// если маршрута нет, возвр. -1
{ int L=1; if (i==m) return 0;
  int a,b, Nvv=g.p[i], Nw;
  int j,k,n=g.nv;
  if (!n ||!Nvv) return -1;
  byte *Vs=new byte[n];
  int *vv= new int[n], *w = new int[n];
  for (k=0;k<n;k++) Vs[k]=0; Vs[i]=1;
  for (j=0;j<Nvv;j++) { b=g.r[i][j];
								if (b==m) goto mm;
                        vv[j]=b; Vs[b]=1; }
  while (Nvv)
    { Nw=0; L++;
      for (j=0;j<Nvv;j++)
        { a=vv[j]; for (k=0;k<g.p[a];k++)
                     { b=g.r[a][k];
                       if (b==m) goto mm;
                       if (Vs[b]==0) { Vs[b]=1; w[Nw++]=b; }}
        }
      for (j=0;j<Nw;j++) vv[j]=w[j];
      Nvv=Nw;
    }
  L=-1;
  mm: delete[] Vs; delete[] vv; delete[] w;
  return L;
}
  graph dlv(const graph& g, int k)
{ if (k<0 || k>=g.nv) return g;
  matad m(g), mx(g.nv-1);
  int i,j,ix,jx;
  for (i=0,ix=0;i<g.nv;i++)
    { if (i==k) continue;
      for (j=0,jx=0;j<g.nv;j++)
        { if (j==k) continue;
          mx.s[ix][jx]=m.s[i][j];
          jx++;
        }
      ix++;
    }
  return graph(mx);
}
  graph double_o_graph(int n)
{ graph g1=o_graph(n);
  graph g2=o_graph(n);
  return join(g1,g2);
}
  int excenter(const graph& g,int i)
{ if (g.form()!=0) { puts("ERROR: excenter(g): g.form()!=0"); exit(0); }
  int L=0;
  int a,b, Nvv=g.p[i], Nw;
  int j,k,n=g.nv;
  if (!n ||!Nvv) return 0;
  byte *Vs=new byte[n];
  int *vv= new int[n], *w = new int[n];
  for (k=0;k<n;k++) Vs[k]=0; Vs[i]=1;
  for (j=0;j<Nvv;j++) { b=g.r[i][j]; vv[j]=b; Vs[b]=1; }
  while (Nvv)
    { Nw=0; L++;
      for (j=0;j<Nvv;j++)
        { a=vv[j]; for (k=0;k<g.p[a];k++)
                     { b=g.r[a][k];
                       if (Vs[b]==0) { Vs[b]=1; w[Nw++]=b; }}
        }
      for (j=0;j<Nw;j++) vv[j]=w[j];
      Nvv=Nw;
    }
  delete[] Vs; delete[] vv; delete[] w;
  return L;
}
  graph fatring(int nv, int c)
{ int k= nv/(c*ln(nv));
  int* V= new int[nv];
  int i,j,p1,p2,a;
  for (i=0;i<nv;i++) V[i]=i;
  matad M; M=nv;
  for (i=0;i<nv-1;i++)
    { p1= i%k;
      for (j=i+1;j<nv;j++)
        { p2=j%k; a= abs(p1-p2);
          if (a<=1 || a==k-1) { M.s[i][j]=1; M.s[j][i]=1; }
        }
    }
  delete[] V;
  return graph(M);
}
  int findcycl(const graph& g, int j, int L, vert* e) // уточнить, для каких графов
{ int n=g.nv;
  int i, q=0, k=0, s=0;
  vert a;
  vert* v= new vert[n]; vert* m= new vert[n]; byte* Mso= new byte[n];
  if (g.p[j]>=2)
    { q=1;
      for (i=0;i<n;i++) { e[i]=0; v[i]=0; m[i]=0; Mso[i]=0; }
      for (i=0;i<g.p[j];i++) Mso[g.r[j][i]]=1;
      v[j]=1; e[0]=(vert)j;
      mm:
      for (i=s; i<g.p[e[k]] && k<L-1; i++)
	     { a=g.r[e[k]][i];
	       if (v[a]==0) { m[k]=(vert)i; v[a]=1; k++;
                         e[k]=a; s=0; goto mm; }
	     }
      if (k<L-1 || k==L-1 && Mso[e[k]]==0)
	     { v[e[k]]=0; k--;
	       if (k<0) { for (i=0;i<n;i++) e[i]=0; q=0; }
          else     { s=m[k]+1; goto mm; }
	     }
    }
  delete[] Mso; delete[] v; delete[] m;
  return q;
}
  graph graph_bic(int nv, word* bic)
{ graph g;
  if (nv==0) return g;
  int i,k,r, J=0;
  word t=0;
  matad M(nv);
  for (i=1;i<nv;i++)
    for (k=0;k<i;k++)
      { if (t==0) t=0x8000;
        r=J/16;
        if (t & bic[r]) M.s[i][k]=M.s[k][i]=1;
        t>>=1; J++;
      }
  g=M; return g;
}
  int gt_r(FILE* in, FILE* out)
{ int n, Nw, Ng=0;
  char str[60];
  word* bic;
  graph g;
  for (;;) { fscanf(in,"%s", str); if (feof(in)) break;
             g<<in;
             if (Ng==0) { n=g.nv; Nw=biclen(n); bic= new word[Nw]; }
             else
               if (n!=g.nv) { printr("gt_r: ОШИБКА: попытка записать в файл \
                                      бикоды графов с разным числом вершин\n");
                              delete bic;
                              return 0;
                            }
             Ng++;
             bic_graph(g,bic);
             write_bic(out,Nw,bic);
           }
  delete bic;
  return Ng;
}
  int hamilt_c(const graph& g, vert* e)  // для каких графов будет работать?
{ int q=isblock(g); if (q==0) return 0;
  int i, n=g.nv, k=0, s=0;
  vert a;
  byte* v  = new byte[n];
  int*  m  = new int[n];
  byte* Mso= new byte[n];
  for (i=0;i<n;i++) { e[i]=0; v[i]=0; m[i]=0; Mso[i]=0; }
  for (i=0;i<g.p[0];i++) Mso[g.r[0][i]]=1;
  v[0]=1;
  mm:
  for (i=s; i<g.p[e[k]]; i++)
    { a=g.r[e[k]][i];
      if (v[a]==0) { m[k]=i; v[a]=1; k++; e[k]=a; s=0; goto mm; }
    }
  if (k<n-1 || k==n-1 && Mso[e[k]]==0)
     { v[e[k]]=0; k--;
       if (k<0) { for (i=0;i<n;i++) e[i]=0; q=0; }
       else     { s=m[k]+1; goto mm; }
     }
  delete[] Mso; delete[] v; delete[] m;
  return q;
}
  ulong hamilt_n(const graph& g)          // // для каких графов будет работать?
{ if (g.nv<3) return 0;
  int q=isblock(g); if (q==0) return 0;
  int a,i, n=g.nv, k=0, s=0;
  ulong Ne=0;
  int*  e = new int[n];
  byte* v = new byte[n];
  int*  m = new int[n];
  byte*  Mso= new byte[n];
  for (i=0;i<n;i++) { e[i]=0; v[i]=0; m[i]=0; Mso[i]=0; }
  for (i=0;i<g.p[0];i++) Mso[g.r[0][i]]=1;
  v[0]=1;
  mm:
  for (i=s; i<g.p[e[k]]; i++)
    { a=g.r[e[k]][i];
      if (v[a]==0) { m[k]=i; v[a]=1; k++; e[k]=a; s=0; goto mm; }
    }
  if (k<n-1 || k==n-1 && Mso[e[k]]==0)
     { mmm:
       v[e[k]]=0; k--; if (k<0) { delete[] Mso;
				                      delete[] v;
				                      delete[] e;
				                      delete[] m; return Ne/2; }
       s=m[k]+1; goto mm; }
  Ne++; goto mmm;
}
  graph hamming(int n, int d)
{ int nv=pow(2,n);
  matad M; M=nv;
  int i,k;
  for (i=0;i<nv-1;i++)
    for (k=i+1;k<nv;k++)
      if (hamdist(i,k)>=d) { M.s[i][k]=1; M.s[k][i]=1; }
  return graph(M);
}
  graph hcube(int m)
{ int i,j, n= pow(2,m);
  matad M(n);
  for (i=1;i<n;i++)
    for (j=0;j<i;j++) if (hamdist(i,j)==1) M.s[i][j]=M.s[j][i]=1;
  return graph(M);
}
  void hread(FILE* f, word& nv, word& nr, ulong& Ng, ulong& KS)
{ errhalt(ftell(f)!=0 ,
          "hread: attemption to read the r-file head not from beginning");
  fread(&nv,2,1,f); fread(&nr,2,1,f);
  fread(&Ng,4,1,f); fread(&KS,4,1,f);
}
  void hwrite(FILE* f, word nv, word nr, ulong Ng, ulong KS)
{ errhalt(ftell(f)!=0 ,
          "hread: attemption to write the r-file head not from beginning");
  fwrite(&nv,2,1,f); fwrite(&nr,2,1,f);
  fwrite(&Ng,4,1,f); fwrite(&KS,4,1,f);
}
  int isblock(const graph& g)
{ if (g.form()!=0) { puts("ERROR: isblock(g): g.form()!=0"); exit(0); }
  int i;
  graph h;
  for (i=0;i<g.nv;i++) { h=dlv(g,i); if (isconn(h)==0) return 0; }
  return 1;
}
  int iscomplete(const graph& g)
{ if ( nrib(g)==g.nv*(g.nv-1)/2 ) return 1; else return 0;
}
  int isconn(const graph& g)
{ int nv=g.nv;
  if (nv==0) return 1;
  int j,k,n,Nvv,Nw;
  vert a,b;
  byte *Vs= new byte[nv];
  vert *vv= new vert[nv];   vert *w= new vert[nv];
  for (j=0;j<nv;j++) Vs[j]=0;
  Vs[0]=1; Nvv=g.p[0]; n=Nvv+1;
  for (j=0;j<Nvv;j++) { b=g.r[0][j]; vv[j]=b; Vs[b]=1; }
  while (Nvv>0) { Nw=0;
                  for (j=0;j<Nvv;j++)
	                 { a=vv[j];
	                   for (k=0;k<g.p[a];k++)
		                  { b=g.r[a][k];
		                    if (Vs[b]==0) { Vs[b]=1; w[Nw++]=b; n++; }
		                  }
	                 }
                  Nvv=Nw;
                  for (j=0;j<Nvv;j++) vv[j]=w[j];
                }
  delete[] Vs; delete[] vv; delete[] w;
  return  n==nv? 1:0;
}
  int isdual(const graph& g)
{ int i,j,k,n=g.nv;
  if (n<2) return 0;
  if (n==2) return 1;
  int a,b,N,Nvv,Nw;
  byte  *Vs= new byte[n];   byte *vvs= new byte[n];
  int *vv= new int[n];  int  *w= new int[n];
  int D=1;
  for (i=0;i<n;i++)
      { for (k=0;k<n;k++) Vs[k]=0; Vs[i]=1;
        Nvv=g.p[i];
        for (j=0;j<Nvv;j++) { b=g.r[i][j]; vv[j]=b; Vs[b]=1; }
	     N=1;
        while (Nvv)
           { N+=Nvv;
	          for (k=0;k<n;k++) vvs[k]=0;
	          for (j=0;j<Nvv;j++) vvs[vv[j]]=1;
             Nw=0;
             for (j=0;j<Nvv;j++)
                 { a=vv[j];
                   for (k=0;k<g.p[a];k++)
                       { b=g.r[a][k];
                         if (vvs[b]==1) { D=0; goto m; }
                         if (Vs[b]==0) { Vs[b]=1; w[Nw++]=b; } } }
             for (j=0;j<Nw;j++) vv[j]=w[j];
             Nvv=Nw;
           }
        if (N==n) break;
      }
  m: delete[] Vs; delete[] vvs; delete[] vv; delete[] w;
  return D;
}
  int isempty(const graph& g)
{ if (g.nv==0) return 1; else return 0;
}
  int iseuler(const graph& g)
{ int i;
  if (isconn(g)) { for (i=0;i<g.nv;i++) if (g.p[i]%2) return 0;
                 return 1;
               }
  else return 0;
}
  int ishamilt(const graph& g)
{ int q=isblock(g); if (q==0) return 0;
  int n=g.nv, k=0;
  int a,i, s=0;
  int* e  = new int[n];
  byte*  v  = new byte[n];
  int* m  = new int[n];
  byte* Mso = new byte[n];
  for (i=0;i<n;i++) { e[i]=0; v[i]=0; m[i]=0; Mso[i]=0; }
  for (i=0;i<g.p[0];i++) Mso[g.r[0][i]]=1;
  v[0]=1;
  mm:
  for (i=s; i<g.p[e[k]]; i++)
    { a=g.r[e[k]][i];
      if (v[a]==0) { m[k]=i; v[a]=1; k++; e[k]=a; s=0; goto mm; }
    }
  if (k<n-1 || k==n-1 && Mso[e[k]]==0)
     { v[e[k]]=0; k--;
       if (k<0) q=0;
       else { s=m[k]+1; goto mm; }
     }
  delete[] Mso; delete[] v; delete[] e; delete[] m;
  return q;
}
  int isisos(const graph& a, const graph& b, int* p)
{ int i,j;
  matad Ma=a, Mb=b;
  for (i=0;i<a.nv;i++)
    for (j=i+1;j<a.nv;j++) if (Ma.s[i][j]!=Mb.s[p[i]][p[j]]) return 0;
  return 1;
}
  int iso(const graph& A, const graph& B)
{ int n=A.nv;
  int i,j,k,s,sp,im,pm;
  int* Av= new int[n];
  int* Bv= new int[n];
  for (i=0;i<n;i++) Av[i]=Bv[i]=i;
  int* st= new int[n]; 							// for (i=0;i<n;i++) st[i]=0; удалить!
  matad MA,MB; MA=A; MB=B;
  for (i=0;i<n-1;i++)
      { pm=A.p[Av[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<A.p[Av[j]]) { pm=A.p[Av[j]]; im=j; }
        swp(Av[i],Av[im]);
      }
  for (i=0;i<n-1;i++)
      { pm=B.p[Bv[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<B.p[Bv[j]]) { pm=B.p[Bv[j]]; im=j; }
        swp(Bv[i],Bv[im]);
      }
  for (sp=1;sp<n;sp++)
      { pm=0; im=sp;
	     for (i=sp;i<n;i++)
            { s=0;
              for (j=0;j<sp;j++) s+=MA.s[Av[i]][Av[j]];
              if (pm<s) { pm=s; im=i; } }
	           swp(Av[sp],Av[im]);
      }
  for (k=0;k<n;k++)
    { swp(Bv[0],Bv[k]);
      for (sp=1;sp<n;sp++)
          { s=sp;
	         mmm:
            for (i=s;i<n;i++)
                { if (A.p[Av[sp]]!=B.p[Bv[i]]) continue;
		            for (j=0;j<sp;j++)
		              if (MB.s[Bv[i]][Bv[j]] != MA.s[Av[sp]][Av[j]]) break;
                  if (j==sp) { swp(Bv[sp],Bv[i]); st[sp]=i; break; }
                }
            if (i==n) { sp--;
                        if (sp==0) break;
                        swp(Bv[sp],Bv[st[sp]]);
			               s=st[sp]+1;
                        goto mmm; } }
      if (sp==n) break; }
  delete[] Av; delete[] Bv; delete[] st;
  return k<n? 1 : 0 ;
}
  int isos(const graph& A, const graph& B, int* p)
{ int q;
  int n=A.nv;
  int i,j,k,s,sp,im,pm;
  int* Av= new int[n];
  int* Bv= new int[n];
  for (i=0;i<n;i++) Av[i]=Bv[i]=i;
  int* st= new int[n];
  matad MA=A, MB=B;
  for (i=0;i<n-1;i++)
      { pm=A.p[Av[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<A.p[Av[j]]) { pm=A.p[Av[j]]; im=j; }
        swp(Av[i],Av[im]);
      }
  for (i=0;i<n-1;i++)
      { pm=B.p[Bv[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<B.p[Bv[j]]) { pm=B.p[Bv[j]]; im=j; }
        swp(Bv[i],Bv[im]);
      }
  for (sp=1;sp<n;sp++)
      { pm=0; im=sp;
        for (i=sp;i<n;i++)
            { s=0;
              for (j=0;j<sp;j++) s+=MA.s[Av[i]][Av[j]];
              if (pm<s) { pm=s; im=i; } }
        swp(Av[sp],Av[im]);
      }
  for (k=0;k<n;k++)
    { swp(Bv[0],Bv[k]);
      for (sp=1;sp<n;sp++)
        { s=sp;
	       mmm:
          for (i=s;i<n;i++)
            { if (A.p[Av[sp]]!=B.p[Bv[i]]) continue;
		        for (j=0;j<sp;j++)
			       if (MB.s[Bv[i]][Bv[j]] != MA.s[Av[sp]][Av[j]]) break;
                if (j==sp) { swp(Bv[sp],Bv[i]); st[sp]=i; break; }
            }
          if (i==n) { sp--;
                      if (sp==0) break;
		                swp(Bv[sp],Bv[st[sp]]);
                      s=st[sp]+1;
                      goto mmm; }
        }
      if (sp==n) break;
    }
  if (k<n) { for (i=0;i<n;i++) p[Av[i]]=Bv[i]; q=1; }
  else { for (i=0;i<n;i++) p[i]=0; q=0; }
  delete[] Av; delete[] Bv; delete[] st;
  return q;
}
  int isregular(const graph& g)
{ int i; int p=g.p[0];
  for (i=1;i<g.nv;i++) if (g.p[i]!=p) return 0;
  return p;
}
  int isucycl(const graph& g)
{ int nv=g.nv;
  if (nv==0) return 1;
  int i,j,k,q,Nvv,Nw;
  int a,b;
  byte *Vs= new byte[nv];
  int *vv= new int[nv];   int *w= new int[nv];
  for (j=0;j<nv;j++) Vs[j]=0;
  for (i=0;i<nv;i++)
     { if (Vs[i]==1) continue;
       Vs[i]=1; Nvv=g.p[i];
       for (j=0;j<Nvv;j++) { b=g.r[i][j]; vv[j]=b; Vs[b]=1; }
       while (Nvv>0)
          { Nw=0;
            for (j=0;j<Nvv;j++)
                { a=vv[j]; q=0;
                  for (k=0;k<g.p[a];k++)
                      { b=g.r[a][k];
                        if (Vs[b]==1) q++;
                        else { Vs[b]=1; w[Nw++]=b; }
                      }
                  if (q>1) return 0;
                }
            Nvv=Nw;
            for (j=0;j<Nvv;j++) vv[j]=w[j];
          }
     }
  delete[] Vs; delete[] vv; delete[] w;
  return 1;
}
  int isulamequ(const graph& A, const graph& B)
{ if (A.nv!=B.nv) return 0;
  int i,j, n=A.nv, Q=1;
  graph *pa= new graph[n], *pb= new graph[n];
  int* q= new int[n];
  for (i=0;i<n;i++) { pa[i]=dlv(A,i); pb[i]=dlv(B,i); q[i]=1; }
  for (i=0;i<n;i++)
    { for (j=0;j<n;j++) if (q[j] && iso(pa[i],pb[j])) { q[j]=0; break; }
      if (j==n) { Q=0; break; }
    }
  delete[] pa; delete[] pb; delete[] q;
  return Q;
}
  int isnonbridge(const graph& g)
{ if (isconn(g)==0) return 0;
  graph h(g); matad M(g);
  int i,j, n=g.nv;
  for (i=0;i<n-1;i++)
    for (j=i+1;j<n;j++) if (M.s[i][j]) { del_r(h,i,j);
                                         if (isconn(h)==0) return 0;
                                         add_r(h,i,j);
                                       }
  return 1;
}
  graph johnson(int n, int w, int d)
{ int nv= Cmb(n,w);
  int* V= new int[nv];
  int* A= new int[w];
  word x;
  int i,k, j=0;
  for (i=0;i<w;i++) A[i]=i;
  int p=1, q;
  while (p)
    { x=0;
      for (i=0;i<w;i++) x|=word(1<<A[i]);
      V[j++]=x;
      k=w-1; q=1;
      while (q) { A[k]++;
		            if (A[k]+w-k-1<n) q=0;
		  				else k--; if (k<0) { p=0; break; }
		  				for (i=k+1;i<w;i++) A[i]=A[i-1]+1;
					 }
    }
  matad M; M=nv;
  for (i=0;i<nv-1;i++)
    for (k=i+1;k<nv;k++)
      if (hamdist(V[i],V[k])>=d) { M.s[i][k]=1; M.s[k][i]=1; }
  delete[] V; delete[] A;
  return graph(M);
}
  graph join(const graph& A, const graph& B)
{ errhalt(A.nv!=B.nv , "join: uncorrect parameters!");
  int n=A.nv;
  graph g=A+B;
  matad M(g);
  int i,j;
  for (i=0;i<n;i++) { j=i+n; M.s[i][j]=1; M.s[j][i]=1; }
  return graph(M);
}
  graph joinc(const graph& A, const graph& B)
{ matad M(A+B);
  int i,j,k;
  for (i=0;i<A.nv;i++)
    for (j=0;j<B.nv;j++) { k=j+A.nv; M.s[i][k]=1; M.s[k][i]=1; }
  return graph(M);
}
  graph k_line(int n, int k)
{ matad M(n);
  int i,j;
  for (i=0;i<n;i++)
    for (j=0;j<n;j++) if (i!=j && abs(i-j)<=k) { M.s[i][j]=1; M.s[j][i]=1; }
  return graph(M);
}
  graph k_ring(int n, int k)
{ matad M(n);
  int i,j,l;
  for (i=0;i<n;i++)
    for (l=1;l<=k;l++) { j=(i+l)%n; M.s[i][j]=M.s[j][i]=1; }
  return graph(M);
}
  graph keller(int n)
{ int nv= pow(4,n);
  int* V= new int[nv];
  int a,xx,i,k,j,p,q,r;
  for (i=0;i<nv;i++) V[i]=i;
  matad M; M=nv;
  for (i=0;i<nv-1;i++)
    for (k=i+1;k<nv;k++)
      { a= V[i]^V[k]; p=q=r=0;
        for (j=0;j<n;j++)
          { xx= a & 3;
            if (p==0 && xx==2) p=1;
            else if (xx)       q=1;
            if (p+q==2) { r=1; break; }
            a>>=2;
          }
        if (r) { M.s[i][k]=1; M.s[k][i]=1; }
      }
  delete[] V;
  return graph(M);
}
  graph line(int n)
{ return graph(k_line(n,1));
}
  matad mat_bic(int nv, word* bic)
{ matad M; if (nv==0) return M;
  int i,k,r, J=0;
  word t=0;
  M=nv;
  for (i=1;i<nv;i++)
    for (k=0;k<i;k++)
      { if (t==0) t=0x8000;
        r=J/16;
        if (t & bic[r]) M.s[i][k]=M.s[k][i]=1;
        t>>=1; J++;
      }
  return M;
}
  graph modmul(const graph& A, const graph& B)
{ int i,j,k,l,r,s;
  matad MA(A), MB(B), MC(A.nv*B.nv);
  for (i=0;i<A.nv;i++)
    for (j=0;j<A.nv;j++)
      for (k=0;k<B.nv;k++)
        for (l=0;l<B.nv;l++)
          { if (i==j || k==l) continue;
            r=i*B.nv+k;
            s=j*B.nv+l;
            if (MA.s[i][j]==MB.s[k][l]) MC.s[r][s]=MC.s[s][r]=1;
          }
  return graph(MC);
}
  int n_orbit(const graph& G)
{ int i,j, M=0, N=G.nv;
  graph* g= new graph[N];
  int* q= new int[N];
  for (i=0;i<N;i++) g[i]=dlv(G,i);
  for (i=0;i<N;i++) q[i]=1;
  for (i=0;i<N;i++)
      { if (q[i]==0) continue;
        M++; q[i]=0;
        for (j=i+1;j<N;j++) if (q[j] && iso(g[i],g[j])) q[j]=0;
      }
  delete[] g; delete[] q;
  return M;
}
  ulong naut(const graph& A)
{ int n=A.nv;
  int i,j,k,im,pm,s,sp;
  ulong q=0;
  int* Av= new int[n];
  int* Bv= new int[n];
  for (i=0;i<n;i++) Av[i]=Bv[i]=i;
  int* st= new int[n]; 							// for (i=0;i<n;i++) st[i]=0; удалить!
  matad M=A;
  for (i=0;i<n-1;i++)
      { pm=A.p[Av[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<A.p[Av[j]]) { pm=A.p[Av[j]]; im=j; }
        swp(Av[i],Av[im]);
      }
  for (i=0;i<n;i++) Bv[i]=Av[i];
  for (sp=1;sp<n;sp++)
    { pm=0; im=sp;
      for (i=sp;i<n;i++)
	     { s=0;
          for (j=0;j<sp;j++) s+=M.s[Av[i]][Av[j]];
          if (pm<s) { pm=s; im=i; }
        }
      swp(Av[sp],Av[im]);
    }
  for (k=0;k<n;k++)
    { swp(Bv[0],Bv[k]);
      for (sp=1;sp<n;sp++)
        { s=sp;
	       mmm:
          for (i=s;i<n;i++)
            { if (A.p[Av[sp]]!=A.p[Bv[i]]) continue;
		        for (j=0;j<sp;j++)
              if (M.s[Bv[i]][Bv[j]] != M.s[Av[sp]][Av[j]]) break;
              if (j==sp) { swp(Bv[sp],Bv[i]); st[sp]=i; break; }
            }
          if (i==n) { sp--;
		                if (sp==0) break;
                      mm: swp(Bv[sp],Bv[st[sp]]);
                      s=st[sp]+1;
                      goto mmm;
          			  }
        }
      if (sp==n) { q++; sp--; goto mm; }
    }
  delete[] Av; delete[] Bv; delete[] st;
  return q;
}
  graph neib(const graph& g, int k)
{ matad Sg=g;
  int n=g.p[k];
  if (n==0) { graph x; return x; }
  matad Sx; Sx=n;
  for (int i=0;i<n;i++)
    for (int j=i+1;j<n;j++) Sx.s[j][i]=Sx.s[i][j]=Sg.s[g.r[k][i]][g.r[k][j]];
  graph x(Sx); return x;
}
  ulong nisos(const graph& A, const graph& B)
{ int n=A.nv;
  int i,j,k,im,pm,s,sp;
  ulong q=0;
  int* Av= new int[n];
  int* Bv= new int[n];
  for (i=0;i<n;i++) Av[i]=Bv[i]=i;
  int* st= new int[n]; 						  // for (i=0;i<n;i++) st[i]=0; удалить!
  matad MA=A, MB=B;
  for (i=0;i<n-1;i++)
      { pm=A.p[Av[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<A.p[Av[j]]) { pm=A.p[Av[j]]; im=j; }
        swp(Av[i],Av[im]);
      }
  for (i=0;i<n-1;i++)
      { pm=B.p[Bv[i]]; im=i;
        for (j=i+1;j<n;j++) if (pm<B.p[Bv[j]]) { pm=B.p[Bv[j]]; im=j; }
        swp(Bv[i],Bv[im]);
      }
  for (sp=1;sp<n;sp++)
    { pm=0; im=sp;
      for (i=sp;i<n;i++)
	     { s=0;
          for (j=0;j<sp;j++) s+=MA.s[Av[i]][Av[j]];
          if (pm<s) { pm=s; im=i; }
        }
      swp(Av[sp],Av[im]);
    }
  for (k=0;k<n;k++)
    { swp(Bv[0],Bv[k]);
      for (sp=1;sp<n;sp++)
        { s=sp;
	       mmm:
          for (i=s;i<n;i++)
            { if (A.p[Av[sp]]!=B.p[Bv[i]]) continue;
		        for (j=0;j<sp;j++)
              if (MB.s[Bv[i]][Bv[j]] != MA.s[Av[sp]][Av[j]]) break;
              if (j==sp) { swp(Bv[sp],Bv[i]); st[sp]=i; break; }
            }
          if (i==n) { sp--; if (sp==0) break;
                      mm: swp(Bv[sp],Bv[st[sp]]);
                      s=st[sp]+1;
                      goto mmm;
                    }
        }
      if (sp==n) { q++; sp--; goto mm; }
    }
  delete[] Av; delete[] Bv; delete[] st;
  return q;
}
  int nrib(const graph& g)
{ int i, R=0;
  for (i=0;i<g.nv;i++) R+=g.p[i];
  return R/2;
}
  ulong ntriangls(const graph& g)
{ matad M=g;
  int i,j,k, n=g.nv;
  ulong t=0;
  for (i=0;i<n-1;i++)
    for (j=i+1;j<n;j++)
      if (M.s[i][j]) { for (k=0;k<n;k++) if (M.s[i][k]+M.s[j][k]==2) t++;
                       M.s[i][j]=M.s[j][i]=0;
                     }
  return t;
}
  graph o_graph(int n)
{ graph x; x=n;
  int i,a,b;
  for (i=0;i<n;i++) { x.p[i]=2; x.r[i]= new vert[2]; }
  for (i=0;i<n;i++) { a=i-1; b=i+1;
                      if (a<0) a=n-1;
                      if (b==n) b=0;
                      x.r[i][0]=(vert)a; x.r[i][1]=(vert)b; }
  return x;
}
  void print(const matad& M)
{ int i,j, n=M.nv;
  printf("  nv=%d \n",n);
  printf(" "); for (i=0;i<n;i++) printf("% d",(i+1)%10); puts("");
  for (i=0;i<n;i++)
    { printf("%d",(i+1)%10);
      for (j=0;j<n;j++) { if (M.s[i][j]) printf(" *"); else printf(" ."); }
      puts("");
    }
}
  void print(const pinv& P)
{ int n=P.nv;
  if (n) { printf("(");
           for (int i=0;i<n-1;i++) printf("%2d,", P.v[i]);
           printf("%2d ) ", P.v[n-1]); }
  else printf("( ) ");
}
  template <class type>
  void print_wr(graph_r<type>& R)
{ int i,j,k=0;
  matad M(R);
  for (i=1;i<R.nv;i++)
    for (j=0;j<i;j++) if (M.s[i][j]) { printf("%2d  edge(%2d,%2d)   weight=",k,i,j);
                                       print(R.wr[i][j]); puts(""); k++;
                                     }
}
  ulong r_gt(FILE* in, FILE* out)
{ char s[10];
  word nv, nr;
  ulong i,Ng,KS;
  hread(in,nv,nr,Ng,KS);
  graph g(nv);
  for (i=0;i<Ng;i++)
    { g.read_r(in);
      sprintf(s,"#%03d",i+1);
      fprintf(out,"%s \n",s); g>>out;
    }
  return Ng;
}
  graph r_inters(const graph& A, const graph& B)
{ errhalt(A.nv!=B.nv,"r_inters: uncorrect parameters: A.nv!=B.nv");
  int i,j, n=A.nv;
  matad Mx(n), Ma(A), Mb(B);
  for (i=0;i<n;i++)
    for (j=i+1;j<n;j++)
      Mx.s[i][j]=Mx.s[j][i]= (byte)(Ma.s[i][j] && Mb.s[i][j] ? 1:0);
  return graph(Mx);
}
  graph  r_union(const graph& A, const graph& B)
{ errhalt(A.nv!=B.nv,"r_union: uncorrect parameters: A.nv!=B.nv");
  int i,j, n=A.nv;
  matad Mx(n), Ma(A), Mb(B);
  for (i=0;i<n;i++)
    for (j=i+1;j<n;j++)
      Mx.s[i][j]=Mx.s[j][i]= (byte)(Ma.s[i][j] || Mb.s[i][j] ? 1:0);
  return graph(Mx);
}
  int radius(const graph& g)
{ int i,ex, n=g.nv, rad=n-1;
  for (i=0;i<n;i++) { ex=excenter(g,i); if (rad>ex) rad=ex; }
  return rad;
}
  graph randgraph(int n, int r)
{ byte s0=0, s1=1;
  int rm= n*(n-1)/2,
      nr= 0;
  int i,k;
  matad M; M=n;
  if (r>rm/2) { r=rm-r;
                s0=1; s1=0;
                for (i=0;i<n;i++)
                  for (k=i+1;k<n;k++) { M.s[i][k]=1; M.s[k][i]=1; }
              }
  while (nr<r)
     { i=random(n); k=random(n);
       if (i!=k && M.s[i][k]==s0) { M.s[i][k]=s1;
				   							M.s[k][i]=s1;
				   							nr++;        } }
  return graph(M);
}
  graph randgraph(int nv, float p)
{ int nr=0, Nr=p*nv*(nv-1)/2+0.5;
  int i,k;
  matad M; M=nv;
  while (nr<Nr)
     { i=random(nv); k=random(nv);
       if (i!=k && M.s[i][k]==0) { M.s[i][k]=1;
				                       M.s[k][i]=1;
				                       nr++;        } }
  return graph(M);
}
  int read_bic(FILE* in, int Nw, word* bic)
{ word c; int r=0;
  for (int k=0;k<Nw;k++) { fread(&c,2,1,in); bic[k]=c; r+=weight(c); }
  return r;
}
  graph renum(const graph& g)
{ int i,k,l,ns, n=g.nv;
  matad M(g);
  for (l=0;l<n;l++)
      { ns=random(n);
        for (k=0;k<n;k++) swp(M.s[l][k],M.s[ns][k]);
        for (i=0;i<n;i++) swp(M.s[i][l],M.s[i][ns]); }
  graph x(M);
  return x;
}
  int rver(FILE* in)					// Возвращаемое значение:
{ word c,r,nv,nr;                // 0 - файл правильный
  ulong k,Ng,KS,S=0;             // 1 - неправильная контрольная сумма
  int i, q=0, rmax, Nw;          // 2 - число ребер не соответствует объявл. в заголовке
  hread(in, nv, nr, Ng, KS);		// 3 - число графов, объявл. в заголовке, равно нулю
  if (nv>1024) { q=4; goto mm; }	// 4 - число вершин, объявл. в заголовке, > 1024
  if (Ng==0)   { q=3; goto mm; } // 5 - число графов в r-файле не соотвует заголовку
  rmax=nv*(nv-1)/2; Nw=(rmax-1)/16+1;
  for (k=0;;k++)
    { r=0;
      for (i=0;i<Nw;i++) { fread(&c,2,1,in); if (feof(in)) goto m001;
                           S+=c;
                           while (c) { r++; c&=(word)(c-1); } }
      if (r!=nr) { q=2; break; }
    }
  m001:
  if (k!=Ng) q=5;
  if (q==0 && KS!=S) q=1;
  mm: rewind(in);
  return q;
}
  graph sanchis(int n, int r, int d)
{ int rm=n*(n-1)/2;
  r= rm-r;
  int v1,v2,p1,p2, ed=0;
  matad M; M=n;
  for (v1=0;v1<n-1;v1++)
    { p1= v1%d;
      for (v2=v1+1;v2<n;v2++)
        { p2=v2%d;
          if (p1==p2) { M.s[v1][v2]=1; M.s[v2][v1]=1; ed++; }
        }
    }
  if (r<ed)
    { printf("sanchis(n,r,d): incorrect value of r: r=%d , maximal r=%d \n",rm-r,rm-ed);
      exit(0); }
  while (ed<r)
    { v1=v2;
      while (v1==v2) { v1= d+random(n-d);
                       v2= random(n);
                     }
      if (M.s[v1][v2]==0) { M.s[v1][v2]=1; M.s[v2][v1]=1; ed++; }
    }
  return ~graph(M);
}
  ulong sigma(const graph& g)
{ int nl=g.nv;
  int i,j,k,p;
  int a,b,Nvv,Nw;
  int s0,s1;
  int* L= new int[nl];
  int** r= new int*[nl];
  byte*  Vs= new byte[nl];   byte* vvs= new byte[nl];
  int* vv= new int[nl];  int*  w= new int[nl];
  int* R = new int[2L*(nl-1)];
  for (i=0;i<nl;i++)
    { for (k=0;k<nl;k++) Vs[k]=0; Vs[i]=1;
      Nvv=g.p[i];
      for (j=0;j<Nvv;j++) { b=g.r[i][j]; vv[j]=b; Vs[b]=1; }
      R[0]=Nvv; p=1;
      while (1)
        { for (j=0;j<nl;j++) vvs[j]=0;
	       for (k=0;k<Nvv;k++) vvs[vv[k]]=1;
          s0=0; s1=0;
          for (j=0;j<Nvv;j++)
		      { a=vv[j];
     		     for (k=0;k<g.p[a];k++)
		          { b=g.r[a][k];
			         if (vvs[b]==1) s0++;
			         if (Vs[b]==0)  s1++; } }
          R[p++]=s0/2;
          if (s1==0) break;
          R[p++]=s1;
          Nw=0;
          for (j=0;j<Nvv;j++)
            { a=vv[j];
              for (k=0;k<g.p[a];k++)
                { b=g.r[a][k];
			         if (Vs[b]==0) { Vs[b]=1; w[Nw++]=b; } } }
          Nvv=Nw;
          for (j=0;j<Nvv;j++) vv[j]=w[j];
        }
	   L[i]=p; r[i]= new int[p];
      for (p=0;p<L[i];p++) r[i][p]=R[p];
    }
  delete[] Vs; delete[] vvs; delete[] vv; delete[] w; delete[] R;
  int im;
  for (i=0;i<nl-1;i++)
    { im=i;
      for (j=i+1;j<nl;j++) if (cmp(L[im],L[j],r[im],r[j])==-1) im=j;
      if (im>i) { swp(L[i],L[im]);
                  R=r[i]; r[i]=r[im]; r[im]=R; } }
  ulong s=0, sr=12173;
  for (i=0;i<nl;i++)
    for (p=0;p<L[i];p++) { s+=sr*r[i][p]; sr*=7; }
  for (i=0;i<nl;i++) delete[] r[i]; delete[] r; delete[] L;
  return s;
}
  graph star(int n)
{ graph g; g=n;
  add_vc(g);
  return g;
}
  int streg(const graph& g, int& m0, int& m1)
{ int q=1;
  matad M(g);
  int i,j,k, n=g.nv;
  int c=n*(n-1)/2;
  int n1=nrib(g), n0=c-n1;
  if (n1==c) { m1=n-2; m0=0; return 1; }
  if (n1==0) { m1=0;   m0=0; return 1; }
  int* r1= new int[n1];
  int* r0= new int[n0];
  m1=m0=0;
  for (i=0;i<n-1;i++)
    for (j=i+1;j<n;j++)
      { c=0;
        for (k=0;k<n;k++) if (M.s[i][k]+M.s[j][k]==2) c++;
        if (M.s[i][j]) r1[m1++]=c; else r0[m0++]=c; }
  m1=r1[0]; m0=r0[0];
  for (i=1;i<n1;i++) if (r1[i]!=m1) { q=0; break; }
  for (i=1;i<n0;i++) if (r0[i]!=m0) { q=0; break; }
  if (q==0) m1=m0=0;
  delete[] r1; delete[] r0;
  return q;
}
  int ver(const graph& g) 		  // возвращает 1, если таблица графа неправильная
{ matad M(g);
  int i,j;
  for (i=0; i<M.nv; i++)
    for (j=i+1; j<M.nv; j++) if (M.s[i][j]!=M.s[j][i]) return 1;
  return 0;
}
  int verification_r(FILE* f)  	// проверка r-файла
{ char* s1="Function verication_r: Verification of r-file:";
  int q= rver(f);
  if (q) puts(s1);
  switch (q)
    { case 1: printr("Неправильная контрольная сумма \n"); break;
  	 	case 2: printr("Число ребер не соответствует объявл. в заголовке \n"); break;
      case 3: printr("Число графов, объявл. в заголовке, равно нулю \n"); break;
      case 4: printr("Число вершин, которое объявлено в заголовке, > 1024 \n"); break;
      case 5: printr("Число графов в r-файле не соотвует заголовку \n"); break;
    };
  return q;
}
  graph wheel(int n)
{ graph g(o_graph(n));
  add_vc(g);
  return g;
}
  void write_bic(FILE* out, int Nw, word* bic)
{ for (int i=0;i<Nw;i++) fwrite(&bic[i],2,1,out);
}
  int two_one(int i, int j)
{ if (i<j) swp(i,j);
  return i*(i-1)/2+j;
}
  void one_two(int k, int& i, int& j)
{ for (i=0;;i++) if ((i+1)*i/2-1>=k) break;
  j=k-i*(i-1)/2;
}
/*----------------------------------------------------------------------------*/
/* классов                         -   7                                      */
/* функций - членов классов        -  31                                      */
/* внешних перегруженных операций  -   6                                      */
/* процедур и функций              -  79                                      */
/* всего функций                   - 116                                      */
/*----------------------------------------------------------------------------*/

Соседние файлы в папке include