#define HELPTEXT \ " cubhamg : Find hamiltonian cycles in sub-cubic graphs\n" \ " infile is the name of the input file in graph6/sparse6 format\n" \ " outfile is the name of the output file in the same format\n" \ "\n" \ " stdin and stdout are the defaults for infile and outfile\n" \ "\n" \ " The output file will have a header\n" \ " if and only if the input file does.\n" \ "\n" \ " Optional switches:\n" \ "\n" \ " -# A parameter useful for tuning (default 100)\n" \ " -v Report nonhamiltonian graphs and noncubic graphs\n" \ " -V .. in addition give a cycle for the hamiltonian ones\n" \ " (with -c, give count for each input)\n" \ " -n#-# If the two numbers are v and i, then the i-th edge\n" \ " out of vertex v is required to be not in the cycle.\n" \ " It must be that i=1..3 and v=0..n-1.\n" \ " -y#-# If the two numbers are v and i, then the i-th edge\n" \ " out of vertex v is required to be in the cycle.\n" \ " It must be that i=1..3 and v=0..n-1.\n" \ " You can use any number of -n/-y switches to force edges.\n" \ " Out of range first arguments are ignored.\n" \ " If -y and -n specify the same edge, -y wins.\n" \ " -i Test + property: for each edge e, there is a hamiltonian\n" \ " cycle using e.\n" \ " -I Test ++ property: for each pair of edges e,e', there is\n" \ " a hamiltonian cycle which uses both e and e'.\n" \ " -o Test - property: for each edge e, there is a hamiltonian \n" \ " cycle avoiding e\n" \ " -O Test -- property: for each pair of nonadjacent edges e,e's,\n" \ " there is a hamiltonian cycle avoiding both. Note that\n" \ " this is trivial unless the girth is at least 5.\n" \ " -x Test +- property: for each pair of edges e,e', there is\n" \ " a hamiltonian cycle which uses e but avoids e'.\n" \ " -e Test 3/4 property: for each edge e, at least 3 of the 4\n" \ " paths of length 3 passing through e lie on hamiltonian cycles.\n" \ " -E Test 3/4+ property: for each edge e failing the 3/4 property,\n" \ " all three ways of joining e to the rest of the graph are\n" \ " hamiltonian avoiding e.\n" \ " -T# Specify a timeout, being a limit on how many search tree\n" \ " nodes are made. If the timeout occurs, the graph is \n" \ " written to the output as if it is nonhamiltonian.\n" \ " -R# Specify the number of repeat attempts for each stage.\n" \ " -F Analyze covering paths from 2 or 4 vertices of degree 2.\n" \ "\n" \ " -b Require biconnectivity\n" \ " -t Require triconnectivity (note: quadratic algorithm)\n" \ "\n" \ " -c Count hamiltonian cycles, output count for each graph.\n" \ " -V, -n and -y can also be used. No graphs are output.\n" \ "\n" \ " -y, -n, -#, -R and -T are ignored for -i, -I, -x, -o, -e, -E, -F\n"
/* BD. McKay, Nov 1995, Aug 1996, Feb 2002, Jul 2008, Nov 2015, Jul 2017 */
staticvoid
check_it(int index, cubgraph g, cubgraph eno, edgevec v1, edgevec v2, int *din, int *dout, int *class, int *farend, int nin, int nv, int stable) /* Check some things */
{ int xdin[MAXN],xdout[MAXN],xnin,v,i,j,k,l,*gv,xin,xout,has1;
for (i = 0; i < nv; ++i) xdin[i] = xdout[i] = 0;
xnin = has1 = 0;
for (v = 0; v < nv; ++v)
{
gv = g[v];
xin = xout = 0; for (i = 0; i < 3; ++i) if (gv[i] >= 0)
{
j = eno[v][i]; if (class[j] == NO) ++xout; if (class[j] == YES) ++xin;
} if (xout != dout[v] || xin != din[v])
{
fprintf(stderr,">E%d degrees of %d: din,dout=%d,%d really %d,%d\n",
index,v,din[v],dout[v],xin,xout);
dummy();
} if (xin == 1) ++has1;
xnin += xin;
}
xnin /= 2; if (xnin != nin)
{
fprintf(stderr,">E%d nin=%d actually %d\n",index,nin,xnin);
dummy();
} if (nin != 0 && !has1)
{
fprintf(stderr,">E%d nin=%d has no in=1\n",index,nin);
dummy();
}
for (i = 0; i < nv; ++i) if (din[i] == 0)
{ if (farend[i] != i)
{
fprintf(stderr,">E%d farend[isolate %d]=%d\n",
index,i,farend[i]);
dummy();
}
} elseif (din[i] == 1)
{
k = -1;
j = i; do
{ for (l = 0; l < 3; ++l) if (g[j][l] >= 0 && g[j][l] != k && class[eno[j][l]] == YES) break;
k = j; if (l < 3) j = g[j][l];
} while (l < 3); if (farend[i] != j)
{
fprintf(stderr,">E%d farend[%d]=%d really %d\n",
index,i,farend[i],j);
dummy();
}
}
if (stable) for (i = 0; i < nv; ++i) if ((dout[i] == 1 && din[i] != 2) || (din[i] == 2 && dout[i] != 1)
|| dout[i] > 1 || din[i] > 2)
{
fprintf(stderr,">E%d din[%d]=%d dout[%d]=%d\n",
index,i,din[i],i,dout[i]);
dummy();
}
}
staticvoid
cubinit(cubgraph g, cubgraph eno, edgevec v1, edgevec v2, int nv, int ne) /* initialise edge numbers, etc. */
{ int *gpx,*gpy,*enop,x,y,i,j,n,en;
n = nv;
en = 0; for (x = 0; x < n; ++x)
{
gpx = g[x];
enop = eno[x]; for (i = 0; i < 3; ++i) if ((y = gpx[i]) < 0)
enop[i] = ne; elseif (y > x)
{
v1[en] = x;
v2[en] = y;
enop[i] = en++;
} else
{
gpy = g[y]; for (j = 0; gpy[j] != x; j++)
{}
enop[i] = eno[y][j];
}
}
if (en != ne)
fprintf(stderr,"%% cubinit got en=%d when ne=%d\n",en,ne);
}
staticint
propagate(cubgraph g, cubgraph eno, nodedata *ndptr, int *nin, int nv) /* propagate classifications: */ /* ans = YES, NO or DUNNO */
{ int v,w,i,status;
nodedata *np; int *gp,*enop,*class,*din,*dout;
status = DUNNO;
np = ndptr; class = np->class;
din = np->din;
dout = np->dout;
while (status == DUNNO && stackptr > stack)
{
POP(v);
gp = g[v];
enop = eno[v]; if (dout[v] == 0)
{ if (din[v] == 2)
{ if (class[enop[0]] == DUNNO) i = 0; elseif (class[enop[1]] == DUNNO) i = 1; else i = 2;
w = gp[i];
status = classout(g,np,v,w,enop[i]);
PUSH(w);
} elseif (din[v] == 3)
status = NO;
} elseif (dout[v] == 1)
{ for (i = 0; i < 3; ++i) if (class[enop[i]] == DUNNO)
{
w = gp[i]; if ((status = classin(g,eno,np,v,w,enop[i],nin,nv))
!= DUNNO) break; else
PUSH(w);
}
} else
status = NO;
}
if (status != NO && *nin == nv) return YES; elsereturn status;
}
staticint
propagate_count(cubgraph g, cubgraph eno, nodedata *ndptr, int *nin, int nv) /* propagate classifications: *ans=NOorDUNNO.
* If a cycle is found add one to numhamcycs and return NO. */
{ int v,w,i,status;
nodedata *np; int *gp,*enop,*class,*din,*dout;
status = DUNNO;
np = ndptr; class = np->class;
din = np->din;
dout = np->dout;
while (status == DUNNO && stackptr > stack)
{
POP(v);
gp = g[v];
enop = eno[v]; if (dout[v] == 0)
{ if (din[v] == 2)
{ if (class[enop[0]] == DUNNO) i = 0; elseif (class[enop[1]] == DUNNO) i = 1; else i = 2;
w = gp[i];
status = classout(g,np,v,w,enop[i]);
PUSH(w);
} elseif (din[v] == 3)
status = NO;
} elseif (dout[v] == 1)
{ for (i = 0; i < 3; ++i) if (class[enop[i]] == DUNNO)
{
w = gp[i]; if ((status = classin(g,eno,np,v,w,enop[i],nin,nv))
!= DUNNO) break; else
PUSH(w);
}
} else
status = NO;
}
if (status != NO && *nin == nv) { ++numhamcycs; return NO; } elsereturn status;
}
staticint
classout(cubgraph g, nodedata *nodat, int v, int w, int en) /* classify edge en = vw out */
{
nodedata *np;
staticint
classin(cubgraph g, cubgraph eno, nodedata *nodat, int v, int w, int en, int *nin, int nv) /* classify edge en = vw in */
{
nodedata *np; int *farend,*gp,fv,fw,i;
gp = g[fv]; if (gp[0] == fw) i = 0; elseif (gp[1] == fw) i = 1; elseif (gp[2] == fw) i = 2; elsereturn DUNNO;
i = eno[fv][i]; if (np->class[i] == DUNNO)
{
PUSH(fv);
PUSH(fw); if (*nin == nv - 1) return classin(g,eno,np,fv,fw,i,nin,nv); else return classout(g,np,fv,fw,i);
}
return DUNNO;
}
staticint
hamnode(cubgraph g, cubgraph eno, edgevec v1, edgevec v2,
nodedata *nodat, int level, int nin, int nv) /* main node for recursion */
{ int i,p,q,status; int v,w,en,*gv,*enov; int *csptr;
#if MAXES if (level > maxlevel) maxlevel = level; #endif
if (++nodecount > maxnodes && maxnodes != NO_LIMIT) return HABORT;
status = propagate(g,eno,nodat,&nin,nv);
if (status != DUNNO) return status;
for (v = nv; --v >= 0;) if (nodat->din[v] == 1) break;
if (v < 0) v = 0;
gv = g[v];
enov = eno[v];
for (i = 0; i < 3; ++i)
{
en = enov[i]; if (nodat->class[en] == DUNNO)
{
w = gv[i];
csptr = classstackptr;
status = classout(g,nodat,v,w,en); if (status == YES) break; if (status == NO)
{ while (classstackptr > csptr)
{
p = *--classstackptr; if (p >= 0)
{ if (nodat->class[p] == YES)
{
--nodat->din[v1[p]];
--nodat->din[v2[p]];
} else
{
--nodat->dout[v1[p]];
--nodat->dout[v2[p]];
}
nodat->class[p] = DUNNO;
} else
{
q = *--classstackptr;
nodat->farend[-p-1] = q;
}
} continue;
}
RESETSTACK;
PUSH(v);
PUSH(w);
status = hamnode(g,eno,v1,v2,nodat,level+1,nin,nv); if (status == YES) break; while (classstackptr > csptr)
{
p = *--classstackptr; if (p >= 0)
{ if (nodat->class[p] == YES)
{
--nodat->din[v1[p]];
--nodat->din[v2[p]];
} else
{
--nodat->dout[v1[p]];
--nodat->dout[v2[p]];
}
nodat->class[p] = DUNNO;
} else
{
q = *--classstackptr;
nodat->farend[-p-1] = q;
}
} if (status == HABORT) return HABORT;
}
}
if (status == DUNNO)
fprintf(stderr,"hamnode returning DUNNO, this can't happen\n"); return status;
}
staticint
hamnode_count(cubgraph g, cubgraph eno, edgevec v1, edgevec v2,
nodedata *nodat, int level, int nin, int nv) /* main node for recursion; version for counting hamcycs. */
{ int i,p,q,status; int v,w,en,*gv,*enov; int *csptr;
#if MAXES if (level > maxlevel) maxlevel = level; #endif
if (++nodecount > maxnodes && maxnodes != NO_LIMIT) return HABORT;
status = propagate_count(g,eno,nodat,&nin,nv);
if (status != DUNNO) return status;
for (v = nv; --v >= 0;) if (nodat->din[v] == 1) break;
if (v < 0) v = 0;
gv = g[v];
enov = eno[v];
for (i = 0; i < 3; ++i)
{
en = enov[i]; if (nodat->class[en] == DUNNO)
{
w = gv[i];
csptr = classstackptr;
status = classout(g,nodat,v,w,en); if (status == YES) break; if (status == NO)
{ while (classstackptr > csptr)
{
p = *--classstackptr; if (p >= 0)
{ if (nodat->class[p] == YES)
{
--nodat->din[v1[p]];
--nodat->din[v2[p]];
} else
{
--nodat->dout[v1[p]];
--nodat->dout[v2[p]];
}
nodat->class[p] = DUNNO;
} else
{
q = *--classstackptr;
nodat->farend[-p-1] = q;
}
} continue;
}
RESETSTACK;
PUSH(v);
PUSH(w);
status = hamnode_count(g,eno,v1,v2,nodat,level+1,nin,nv); if (status == YES) break; while (classstackptr > csptr)
{
p = *--classstackptr; if (p >= 0)
{ if (nodat->class[p] == YES)
{
--nodat->din[v1[p]];
--nodat->din[v2[p]];
} else
{
--nodat->dout[v1[p]];
--nodat->dout[v2[p]];
}
nodat->class[p] = DUNNO;
} else
{
q = *--classstackptr;
nodat->farend[-p-1] = q;
}
} if (status == HABORT) return HABORT;
}
}
if (status == DUNNO)
fprintf(stderr,"hamnode returning DUNNO, this can't happen\n"); return status;
}
staticint
cubham(cubgraph g, cubgraph eno, edgevec initclass, edgevec v1, edgevec v2,
vertvec cycle, edgevec outclass, int nv, int ne) /* external interface */
{ int i,j,status,nin,v,w;
for (i = ne; --i >= 0;)
hcnodat.class[i] = DUNNO; if (3*nv > 2*ne) hcnodat.class[ne] = NO;
for (i = nv; --i >= 0;)
{
hcnodat.din[i] = hcnodat.dout[i] = 0;
hcnodat.farend[i] = i;
onstack[i] = 0;
}
nin = 0;
stacklev = 0;
RESETSTACK;
for (i = nv; --i >= 0;)
{ if (g[i][1] < 0) return NO; if (g[i][2] < 0)
{
hcnodat.dout[i] = 1;
PUSH(i);
}
}
status = DUNNO;
classstackptr = classstack; if (initclass) for (i = 0; i < ne; ++i) if (initclass[i] != DUNNO)
{
v = v1[i];
w = v2[i]; if (initclass[i] == NO)
{ if (hcnodat.class[i] == YES)
status = NO; elseif (hcnodat.class[i] == DUNNO)
{ if (hcnodat.dout[v] == 0)
{
status = classout(g,&hcnodat,v,w,i);
PUSH(v);
PUSH(w);
} else
status = NO;
}
} elseif (initclass[i] == YES)
{ if (hcnodat.class[i] == NO)
status = NO; elseif (hcnodat.class[i] == DUNNO)
{ if (hcnodat.din[v] < 2)
{
status = classin(g,eno,&hcnodat,v,w,i,&nin,nv);
PUSH(v);
PUSH(w);
} else
status = NO;
}
}
if (status != DUNNO) break;
}
if (status == DUNNO)
status = hamnode(g,eno,v1,v2,&hcnodat,0,nin,nv);
if (status == YES && cycle)
{
w = -1;
v = 0;
cycle[0] = 0; for (i = 1; i < nv; ++i)
{ for (j = 0; g[v][j] == w || hcnodat.class[eno[v][j]] != YES; ++j)
{}
w = v;
v = g[v][j];
cycle[i] = v;
}
} if (status == YES && outclass) for (i = 0; i < ne; ++i)
outclass[i] = hcnodat.class[i];
return status;
}
static nauty_counter
cubham_count(cubgraph g, cubgraph eno, edgevec initclass, edgevec v1, edgevec v2,
vertvec cycle, edgevec outclass, int nv, int ne) /* external interface, counting version; returns number of cycles */
{ int i,j,status,nin,v,w;
numhamcycs = 0;
for (i = ne; --i >= 0;)
hcnodat.class[i] = DUNNO; if (3*nv > 2*ne) hcnodat.class[ne] = NO;
for (i = nv; --i >= 0;)
{
hcnodat.din[i] = hcnodat.dout[i] = 0;
hcnodat.farend[i] = i;
onstack[i] = 0;
}
nin = 0;
stacklev = 0;
RESETSTACK;
for (i = nv; --i >= 0;)
{ if (g[i][1] < 0) return NO; if (g[i][2] < 0)
{
hcnodat.dout[i] = 1;
PUSH(i);
}
}
status = DUNNO;
classstackptr = classstack; if (initclass) for (i = 0; i < ne; ++i) if (initclass[i] != DUNNO)
{
v = v1[i];
w = v2[i]; if (initclass[i] == NO)
{ if (hcnodat.class[i] == YES)
status = NO; elseif (hcnodat.class[i] == DUNNO)
{ if (hcnodat.dout[v] == 0)
{
status = classout(g,&hcnodat,v,w,i);
PUSH(v);
PUSH(w);
} else
status = NO;
}
} elseif (initclass[i] == YES)
{ if (hcnodat.class[i] == NO)
status = NO; elseif (hcnodat.class[i] == DUNNO)
{ if (hcnodat.din[v] < 2)
{
status = classin(g,eno,&hcnodat,v,w,i,&nin,nv);
PUSH(v);
PUSH(w);
} else
status = NO;
}
}
if (status != DUNNO) break;
}
if (status == DUNNO)
status = hamnode_count(g,eno,v1,v2,&hcnodat,0,nin,nv);
if (status != NO)
gt_abort(">E hamnode_count() should return NO\n");
staticint
isham(cubgraph cub, int n, int ne, int weight, int *vv, int *vi, int nvv, int *yy, int *yi, int nyy, int *cyc) /* test if hamiltonian; optionally return a cycle Forbidthevi[i]-thnbrofvv[i],fori=0..nvv-1 Forcetheyi[i]-thnbrofyy[i],fori=0..nyy-1
WARNING: vi[i]/yi[i] is numbered starting at 1 */
{ int i,j,k; int nmax,ch;
cubgraph cubcopy;
edgevec v1,v2,initclass,outclass; int perm[MAXN],pinv[MAXN]; double tmp;
for (i = 0; i < nvv; ++i) if (vv[i] < n) initclass[eno[vv[i]][vi[i]-1]] = NO; for (i = 0; i < nyy; ++i) if (yy[i] < n) initclass[eno[yy[i]][yi[i]-1]] = YES;
for (i = 0; i < nvv; ++i) if (vv[i] < n) initclass[eno[perm[vv[i]]][vi[i]-1]] = NO; for (i = 0; i < nyy; ++i) if (yy[i] < n) initclass[eno[perm[yy[i]]][yi[i]-1]] = YES;
static nauty_counter
numham(cubgraph cub, int n, int ne, int weight, int *vv, int *vi, int nvv, int *yy, int *yi, int nyy, int *cyc) /* Count hamiltonian cycles. Forbidthevi[i]-thnbrofvv[i],fori=0..nvv-1 Forcetheyi[i]-thnbrofyy[i],fori=0..nyy-1
WARNING: vi[i]/yi[i] is numbered starting at 1 */
{ int i,j,k; int nmax,ch;
cubgraph cubcopy;
edgevec v1,v2,initclass,outclass; int perm[MAXN],pinv[MAXN]; double tmp;
for (i = 0; i < nvv; ++i) if (vv[i] < n) initclass[eno[vv[i]][vi[i]-1]] = NO; for (i = 0; i < nyy; ++i) if (yy[i] < n) initclass[eno[yy[i]][yi[i]-1]] = YES;
staticint
optadd(cubgraph cub, int v1, int v2) /* v1 and v2 must have degree 2 and be distinct.
Add edge v1-v2 if not already present; return index of edge in cub[v1]. */
{ if (cub[v1][0] == v2) return0; if (cub[v1][1] == v2) return1;
cub[v1][2] = v2;
cub[v2][2] = v1; return2;
}
staticvoid
dofragment(nauty_counter id, cubgraph cub, int n, int ne, int weight) /* Test for coverage by one or two paths between vertices of degree 2 */
{ int i,i1,i2,i3,i4; int v1,v2,v3,v4,j1,j3; int deg2[MAXN],ndeg2; int yy[3],yi[3],newne; int cyc[MAXN]; int status;
ndeg2 = 0; for (i = 0; i < n; ++i)
{ if (cub[i][0] < 0 || cub[i][1] < 0)
gt_abort(">E -F forbids degree 0,1\n");
if (cub[i][2] < 0) deg2[ndeg2++] = i;
}
printf("Input " COUNTER_FMT ":",id); for (i = 0; i < ndeg2; ++i) printf(" %d",deg2[i]);
printf("\n");
printf(" Pairs: "); for (i1 = 0; i1 < ndeg2; ++i1) for (i2 = i1+1; i2 < ndeg2; ++i2)
{
v1 = deg2[i1]; v2 = deg2[i2];
j1 = optadd(cub,v1,v2);
yy[0] = v1; yi[0] = j1+1;
newne = ne + (j1==2);
status = isham(cub,n,newne,weight,NULL,NULL,0,yy,yi,1,cyc); if (status == HABORT)
printf(" T%d-%d",v1,v2); if (status == NO)
printf(" N%d-%d",v1,v2); else
{
printf(" Y%d-%d",v1,v2); if (verbose > 1)
{
printf("["); for (i = 0; i < n; ++i) printf(" %d",cyc[i]);
printf("]\n");
}
}
cub[v1][2] = cub[v2][2] = -1;
}
printf("\n");
printf(" Quartets: "); for (i1 = 0; i1 < ndeg2; ++i1) for (i2 = i1+1; i2 < ndeg2; ++i2) for (i3 = i1+1; i3 < ndeg2; ++i3) for (i4 = i3+1; i4 < ndeg2; ++i4)
{ if (i3 == i2 || i4 == i2) continue;
staticint
hasinout(cubgraph cub, int n, int ne, int *x0, int *x1, int *y0, int *y1, int limit) /* test if cub has in-out (+-) property */
{
edgevec v1,v2,initclass,outclass;
set *d0,*di,*dii; int i,ii,j,jj; int me,nbad;
DYNALLSTAT(graph,done,done_sz);
staticint
hasinin(cubgraph cub, int n, int ne, int *x0, int *x1, int *y0, int *y1, int limit) /* test if cub has in-in (++) property */
{
edgevec v1,v2,initclass,outclass;
set *d0,*di,*dii; int i,ii,j,jj; int me,nbad;
DYNALLSTAT(graph,done,done_sz);
staticint
hasoutout(cubgraph cub, int n, int ne, int *x0, int *x1, int *y0, int *y1, int limit) /* test if cub has out-out (--) property */
{
edgevec v1,v2,initclass,outclass;
set *d0,*di,*dii; int i,ii,j,jj; int me,nbad;
DYNALLSTAT(graph,done,done_sz);
staticint
hasin(cubgraph cub, int n, int ne, int *x0, int *x1, int limit) /* test if cub has "in" property */
{
edgevec v1,v2,initclass,outclass;
boolean done[MAXNE]; int i,ii; int nbad;
cubinit(cub,eno,v1,v2,n,ne); for (i = 0; i < ne; ++i)
{
initclass[i] = DUNNO;
done[i] = FALSE;
}
maxnodes = NO_LIMIT;
nbad = 0;
for (i = 0; i < ne; ++i) if (!done[i])
{
initclass[i] = YES;
++numtries[0]; if (cubham(cub,eno,initclass,v1,v2,NULL,outclass,n,ne) == NO)
{
x0[nbad] = v1[i]; x1[nbad] = v2[i];
++nbad; if (nbad >= limit) return nbad;
} else
{ for (ii = i; ii < ne; ++ii) if (outclass[ii] == YES) done[ii] = TRUE;
}
staticint
hase34(cubgraph cub, int n, int ne, int *x0, int *x1, int *why, boolean plus, int limit) /* test if cub has "e34" property */
{
edgevec v1,v2,initclass,outclass; int ea[4*MAXNE],eb[4*MAXNE],ec[4*MAXNE];
boolean done[4*MAXNE]; int count[MAXNE]; int i,ii; int vi,nbad,pluswhy; staticint pop[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
if (3*n != 2*ne)
{
fprintf(stderr, "cubhamg: hase34() not implemented for noncubic graphs\n"); exit(1);
}
cubinit(cub,eno,v1,v2,n,ne); for (i = 0; i < ne; ++i)
{
initclass[i] = DUNNO;
count[i] = 0;
}
for (i = ii = 0; i < ne; ++i)
{
eb[ii] = eb[ii+1] = eb[ii+2] = eb[ii+3] = i;
done[ii] = done[ii+1] = done[ii+2] = done[ii+3] = FALSE;
vi = v1[i]; if (eno[vi][0] != i) ea[ii++] = eno[vi][0]; if (eno[vi][1] != i) ea[ii++] = eno[vi][1]; if (eno[vi][2] != i) ea[ii++] = eno[vi][2];
ea[ii] = ea[ii-2];
ea[ii+1] = ea[ii-1];
vi = v2[i]; if (eno[vi][0] != i) ec[ii++] = eno[vi][0]; if (eno[vi][1] != i) ec[ii++] = eno[vi][1]; if (eno[vi][2] != i) ec[ii++] = eno[vi][2];
ec[ii-4] = ec[ii-3] = ec[ii-2];
ec[ii-2] = ec[ii-1];
}
maxnodes = NO_LIMIT;
nbad = 0;
for (i = 0; i < 4*ne; ++i) if (!done[i])
{
initclass[ea[i]] = YES;
initclass[eb[i]] = YES;
initclass[ec[i]] = YES;
++numtries[0]; if (cubham(cub,eno,initclass,v1,v2,NULL,
outclass,n,ne) == YES) for (ii = i; ii < 4*ne; ++ii) if (!done[ii] && outclass[ea[ii]] == YES &&
outclass[eb[ii]] == YES && outclass[ec[ii]] == YES)
{
done[ii] = TRUE;
count[eb[ii]] |= 1 << (ii & 3);
}
++numtries[0];
initclass[ea[i]] = DUNNO;
initclass[eb[i]] = DUNNO;
initclass[ec[i]] = DUNNO;
}
pluswhy = 0; for (i = 0; i < ne; ++i) if (pop[count[i]] < 3
&& (!plus || !eplus(cub,n,ne,v1[i],v2[i],&pluswhy)))
{
x0[nbad] = v1[i]; x1[nbad] = v2[i];
why[nbad] = (pluswhy << 4) | count[i];
++nbad; if (nbad >= limit) return nbad;
}
#if0 staticint
oldhasout(cubgraph cub, int n, int ne, int *x0, int *x1, int limit) /* test if cub has "out" property */
{
edgevec v1,v2,initclass,outclass;
boolean done[MAXNE]; int i,ii; int nbad;
cubinit(cub,eno,v1,v2,n,ne); for (i = 0; i < ne; ++i)
{
initclass[i] = DUNNO;
done[i] = FALSE;
}
maxnodes = NO_LIMIT;
nbad = 0;
for (i = 0; i < ne; ++i) if (!done[i])
{
initclass[i] = NO;
++numtries[0]; if (cubham(cub,eno,initclass,v1,v2,NULL,outclass,n,ne) == NO)
{
x0[nbad] = v1[i]; x1[nbad] = v2[i];
++nbad; if (nbad >= limit) return nbad;
} else
{ for (ii = i; ii < ne; ++ii) if (outclass[ii] == NO) done[ii] = TRUE;
}
staticint
hasout(cubgraph cub, int n, int ne, int weight, int *x0, int *x1, int limit) /* test if cub has "out" property Returnsare-2fortimeout,-1fornonhamiltonian,otherwise
number of edges not present in any cycle */
{
cubgraph done; int cyc[MAXN]; int vv[2],vi[2]; int nbad,ch; int i,j,ii,jj,x,y,z;
nbad = 0;
for (i = 0; i < n; ++i) done[i][0] = done[i][1] = done[i][2] = 0;
ch = isham(cub,n,ne,weight,vv,vi,0,NULL,NULL,0,cyc); if (ch == HABORT) return -2; if (ch == NO) return -1;
for (i = 0; i < n; ++i)
{
x = cyc[i];
y = cyc[i==n-1?0:i+1];
z = cyc[i==0?n-1:i-1]; for (j = 0; j < 3; ++j) if (cub[x][j] >= 0 &&
cub[x][j] != y && cub[x][j] != z) break; if (j < 3) done[x][j] = 1;
}
for (ii = 0; ii < n; ++ii) for (jj = 0; jj < 3; ++jj)
{ if (cub[ii][jj] > ii && !done[ii][jj])
{
vv[0] = ii;
vi[0] = jj+1;
ch = isham(cub,n,ne,weight,vv,vi,1,NULL,NULL,0,cyc); if (ch == HABORT) return -2; if (ch == NO)
{
x0[nbad] = ii;
x1[nbad] = cub[ii][jj];
++nbad;
} else
{ for (i = 0; i < n; ++i)
{
x = cyc[i];
y = cyc[i==n-1?0:i+1];
z = cyc[i==0?n-1:i-1]; for (j = 0; j < 3; ++j) if (cub[x][j] >= 0 &&
cub[x][j] != y && cub[x][j] != z) break; if (j < 3) done[x][j] = 1;
}
static boolean
biconnected_cub(cubgraph cub, int n) /* test whether cub is biconnected */
{ int i,sp,v,w,x;
set visited[MAXM]; int numvis,num[MAXN],lp[MAXN],stack[MAXN]; int m,*gv;
for (;;)
{ for (i = 0; i < 3; ++i) if (gv[i] >= 0 && !ISELEMENT(visited,gv[i])) break;
if (i < 3)
{
w = v;
v = gv[i]; /* visit next child */
stack[++sp] = v;
gv = (int*)cub[v];
ADDELEMENT(visited,v);
lp[v] = num[v] = numvis++;
for (i = 0; i < 3; ++i)
{
x = gv[i]; if (x >= 0 && x != w && ISELEMENT(visited,x)) if (num[x] < lp[v]) lp[v] = num[x];
}
} else
{
w = v; /* back up to parent */ if (sp <= 1) return numvis == n;
v = stack[--sp];
gv = (int*)cub[v]; if (lp[w] >= num[v]) returnFALSE; if (lp[w] < lp[v]) lp[v] = lp[w];
}
}
}
static boolean
biconnected_cub_v(cubgraph cub, int vv, int n) /* test whether cub-vv is biconnected */
{ int i,sp,v,w,x,start;
set visited[MAXM]; int numvis,num[MAXN],lp[MAXN],stack[MAXN]; int m,*gv;
for (;;)
{ for (i = 0; i < 3; ++i) if (gv[i] >= 0 && !ISELEMENT(visited,gv[i])) break;
if (i < 3)
{
w = v;
v = gv[i]; /* visit next child */
stack[++sp] = v;
gv = (int*)cub[v];
ADDELEMENT(visited,v);
lp[v] = num[v] = numvis++;
for (i = 0; i < 3; ++i)
{
x = gv[i]; if (x >= 0 && x != w && x != vv && ISELEMENT(visited,x)) if (num[x] < lp[v]) lp[v] = num[x];
}
} else
{
w = v; /* back up to parent */ if (sp <= 1) return numvis == n-1;
v = stack[--sp];
gv = (int*)cub[v]; if (lp[w] >= num[v]) returnFALSE; if (lp[w] < lp[v]) lp[v] = lp[w];
}
}
}
static boolean
biconnected_v(graph *g, int vv, int m, int n) /* test whether g-vv is biconnected */ /* version for arbitrary sizes */
{ int i,sp,v,w;
setword ww;
set sw[MAXM],visited[MAXM]; int numvis,num[MAXN],lp[MAXN],stack[MAXN]; int start;
set *gv;
for (;;)
{ for (i = 0; i < m; ++i) if ((ww = gv[i] & ~visited[i])) break; /* = */
if (i < m)
{
w = v;
v = TIMESWORDSIZE(i) + FIRSTBIT(ww); /* visit next child */
stack[++sp] = v;
gv = (set*)g + m*v;
ADDELEMENT(visited,v);
lp[v] = num[v] = numvis++; for (i = 0; i < m; ++i)
sw[i] = gv[i] & visited[i];
DELELEMENT(sw,w);
DELELEMENT(sw,vv);
for (i = 0; i < m; ++i)
{
ww = sw[i]; while (ww)
{
TAKEBIT(w,ww);
w += TIMESWORDSIZE(i); if (num[w] < lp[v]) lp[v] = num[w];
}
}
} else
{
w = v; /* back up to parent */ if (sp <= 1) return numvis == n-1;
v = stack[--sp];
gv = (set*)g + m*v; if (lp[w] >= num[v]) returnFALSE; if (lp[w] < lp[v]) lp[v] = lp[w];
}
}
}
static boolean
gtocub(graph *g, int m, int n, cubgraph cub, int *pne) /* Convert nauty-format graph into cubgraph. Returns FALSE if there *areanyverticesofdegree4ormore.
*/
{ int i,j,nde;
set *gi;
nde = 0; for (i = 0, gi = (set*)g; i < n; ++i, gi += m)
{
cub[i][0] = cub[i][1] = cub[i][2] = -1;
j = nextelement(gi,m,-1); if (j < 0) continue;
cub[i][0] = j;
++nde;
j = nextelement(gi,m,j); if (j < 0) continue;
cub[i][1] = j;
++nde;
j = nextelement(gi,m,j); if (j < 0) continue;
cub[i][2] = j;
++nde; if (nextelement(gi,m,j) >= 0) returnFALSE;
}
static boolean
sgtocub(sparsegraph *sg, cubgraph cub, int *pne) /* Convert sparse-format graph into cubgraph. Returns FALSE if there *areanyverticesofdegree4ormore.
*/
{ int *d,*e;
size_t *v; int n,i,j,vi; unsignedlongint nde;
nde = 0;
n = sg->nv;
SG_VDE(sg,v,d,e); for (i = 0; i < n; ++i)
{ if (d[i] >= 4) returnFALSE;
vi = v[i];
if (triconn) biconn = FALSE; if (e34) in = out = outout = inin = inout = FALSE; if (inout) in = out = outout = inin = FALSE; if (inin) in = out = outout = FALSE; if (out) in = FALSE; if (testing) out = TRUE;
if (codetype&HAS_HEADER)
{ if (codetype&SPARSE6) writeline(outfile,SPARSE6_HEADER); else writeline(outfile,GRAPH6_HEADER);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.