Добавил:
Upload
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
/*----------------------------------------------------------------------------*/
/* Пакет 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 */
/*----------------------------------------------------------------------------*/