static void makeprism_sg(sparsegraph *sg, sparsegraph *sh) /* Make the cartesian product sh = sg x K2. sh must be initialized. */ { size_t *v,*vv,vi,vvi; int *d,*dd,*e,*ee; int i,j,n; SG_VDE(sg,v,d,e); n = sg->nv; SG_ALLOC(*sh,2*sg->nv,2*(n+sg->nde),"makeprism_sg"); sh->nv = 2*n; sh->nde = 2*(n+sg->nde); SG_VDE(sh,vv,dd,ee); vvi = 0; for (i = 0; i < n; ++i) { vi = v[i]; dd[2*i] = dd[2*i+1] = d[i] + 1; vv[2*i] = vvi; for (j = 0; j < d[i]; ++j) ee[vvi++] = 2*e[vi++]; ee[vvi++] = 2*i+1; vi = v[i]; vv[2*i+1] = vvi; for (j = 0; j < d[i]; ++j) ee[vvi++] = 2*e[vi++]+1; ee[vvi++] = 2*i; } }
static void subdivisiongraph(sparsegraph *g, int k, sparsegraph *h) /* h := subdivision graph of g, k new vertices per edge */ { DYNALLSTAT(size_t,eno,eno_sz); /* edge number */ int *ge,*gd,*he,*hd; size_t *gv,*hv; int gnv,hnv; size_t i,j,l,gnde,hnde,num; size_t hi,lo,mid,w; if (k == 0) { copy_sg(g,h); return; } sortlists_sg(g); SG_VDE(g,gv,gd,ge); gnv = g->nv; gnde = g->nde; DYNALLOC1(size_t,eno,eno_sz,gnde,"subdivideg"); hnv = gnv + k*(gnde/2); if (hnv <= 0 || (gnde > 0 && ((size_t)(hnv-gnv))/(gnde/2) != k)) gt_abort(">E subdivideg: output graph too large\n"); hnde = gnde * (k+1); if (hnde/(k+1) != gnde) gt_abort(">E subdivideg: output graph too large\n"); num = 0; for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]; ++j) { if (ge[j] == i) gt_abort(">E subdivideg can't handle undirected loops\n"); else if (ge[j] > i) eno[j] = num++; else { lo = gv[ge[j]]; hi = lo + gd[ge[j]] - 1; while (lo <= hi) { mid = lo + (hi-lo)/2; if (ge[mid] == i) break; else if (ge[mid] < i) lo = mid+1; else hi = mid-1; } if (lo > hi) gt_abort(">E subdivideg : binary search failed\n"); eno[j] = eno[mid]; } } } SG_ALLOC(*h,hnv,hnde,"subdivideg"); h->nv = hnv; h->nde = hnde; SG_VDE(h,hv,hd,he); for (i = 0; i < gnv; ++i) { hd[i] = gd[i]; hv[i] = gv[i]; } for (i = gnv; i < hnv; ++i) { hd[i] = 2; hv[i] = gnde + 2*(i-gnv); } for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]; ++j) if (ge[j] > i) { w = gnv + k*eno[j]; he[j] = w; he[hv[w]] = i; for (l = 1; l < k; ++l) { he[hv[w]+1] = w+1; he[hv[w+1]] = w; ++w; } } else { w = gnv + k*eno[j] + k - 1; he[j] = w; he[hv[w]+1] = i; } } }
static int hamheur(sparsegraph *sg, unsigned long limit, int *cyc) /* Try up to limit, fill cyc if YES and cyc!=NULL */ { DYNALLSTAT(int,path,path_sz); DYNALLSTAT(int,work,work_sz); DYNALLSTAT(int,pos,pos_sz); /* position on path or -1 */ int end0,end1,v0,v1; size_t *v; int n,*e,*d,len,d0,*e0,d1,*e1,dx,*ex; int i,ix,x,j,w,vext,exts; unsigned long count; boolean left,cycle; long ran; SG_VDE(sg,v,d,e); n = sg->nv; if (n < 3) return NO; DYNALLOC1(int,path,path_sz,2*n+4,"malloc"); DYNALLOC1(int,pos,pos_sz,n,"malloc"); DYNALLOC1(int,work,work_sz,n,"malloc"); for (i = 0; i < n; ++i) { if (d[i] < 2) return NO; pos[i] = -1; } count = 0; v0 = KRAN(n); v1 = e[v[v0]+KRAN(d[v0])]; end0 = n+1; end1 = n+2; path[end0] = v0; pos[v0] = end0; path[end1] = v1; pos[v1] = end1; len = 2; for (; count < limit;) { /* First look for an extension, but note if cycle */ v0 = path[end0]; v1 = path[end1]; exts = 0; d0 = d[v0]; e0 = e + v[v0]; cycle = FALSE; ran = NEXTRAN; for (i = 0; i < d0; ++i) { w = e0[i]; if (pos[w] < 0) { ++exts; if (ran%exts == 0) {left = TRUE; vext = w;} } else if (w == v1) cycle = TRUE; } d1 = d[v1]; e1 = e + v[v1]; ran = NEXTRAN; for (i = 0; i < d1; ++i) { w = e1[i]; if (pos[w] < 0) { ++exts; if (ran%exts == 0) {left = FALSE; vext = w;} } } if (exts > 0) { if (left) { --end0; path[end0] = vext; pos[vext] = end0; } else { ++end1; path[end1] = vext; pos[vext] = end1; } ++len; continue; } /* Can't extend but a cycle was found */ if (cycle) { if (len == n) { if (cyc) { j = 0; for (i = pos[0]; i <= end1; ++i) cyc[j++] = path[i]; for (i = end0; i < pos[0]; ++i) cyc[j++] = path[i]; } return YES; } ix = end0 + KRAN(len); for (i = 0; i < len; ++i) { x = path[ix]; exts = 0; dx = d[x]; ex = e + v[x]; ran = NEXTRAN; for (j = 0; j < dx; ++j) { w = ex[j]; if (pos[w] < 0) { ++exts; if (ran%exts == 0) vext = w; } } if (exts > 0) break; if (ix == end1) ix = end0; else ++ix; } if (i == len) return NO; /* isolated component */ work[0] = vext; j = 1; for (i = ix; i <= end1; ++i) work[j++] = path[i]; for (i = end0; i < ix; ++i) work[j++] = path[i]; for (i = 0; i < j; ++i) { path[end0+i] = work[i]; pos[work[i]] = end0+i; } ++end1; ++len; continue; } /* In the last resort, do a sideways move. */ exts = 0; d0 = d[v0]; e0 = e + v[v0]; ran = NEXTRAN; for (i = 0; i < d0; ++i) { w = e0[i]; if (pos[w] >= 0 && w != path[end0+1]) { ++exts; if (ran%exts == 0) {left = TRUE; vext = w;} } } d1 = d[v1]; e1 = e + v[v1]; ran = NEXTRAN; for (i = 0; i < d1; ++i) { w = e1[i]; if (pos[w] >= 0 && w != path[end1-1]) { ++exts; if (ran%exts == 0) {left = FALSE; vext = w;} } } if (left) { i = end0; j = pos[vext]-1; } else { i = pos[vext]+1; j = end1; } for (; i < j; ++i, --j) { w = path[i]; path[i] = path[j]; path[j] = w; pos[path[i]] = i; pos[path[j]] = j; } ++count; } return TIMEOUT; }
static void linegraph(sparsegraph *g, sparsegraph *h) /* h := linegraph of g */ { DYNALLSTAT(size_t,eno,eno_sz); /* edge number */ int *ge,*gd,*he,*hd; size_t *gv,*hv; int gnv,hnv; size_t i,j,k,gnde,hnde,xhnde,num; size_t hi,lo,mid,v,w; sortlists_sg(g); SG_VDE(g,gv,gd,ge); gnv = g->nv; gnde = g->nde; DYNALLOC1(size_t,eno,eno_sz,gnde,"linegraphg"); hnv = gnde/2; if (hnv != gnde/2) gt_abort(">E linegraphg: too many input edges\n"); hnde = 0; num = 0; for (i = 0; i < gnv; ++i) { xhnde = hnde; hnde += gd[i]*((size_t)gd[i]-1); if (hnde < xhnde) gt_abort(">E linegraphg: too many output edges\n"); for (j = gv[i]; j < gv[i]+gd[i]; ++j) { if (ge[j] == i) gt_abort(">E linegraphg can't handle loops\n"); else if (ge[j] > i) eno[j] = num++; else { lo = gv[ge[j]]; hi = lo + gd[ge[j]] - 1; while (lo <= hi) { mid = lo + (hi-lo)/2; if (ge[mid] == i) break; else if (ge[mid] < i) lo = mid+1; else hi = mid-1; } if (lo > hi) gt_abort(">E linegraphg : binary search failed\n"); eno[j] = eno[mid]; } } } SG_ALLOC(*h,hnv,hnde,"linegraphg"); h->nv = hnv; h->nde = hnde; SG_VDE(h,hv,hd,he); for (i = 0; i < hnv; ++i) hd[i] = 0; for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]; ++j) hd[eno[j]] += gd[i]-1; } hv[0] = 0; for (i = 1; i < hnv; ++i) hv[i] = hv[i-1] + hd[i-1]; for (i = 0; i < hnv; ++i) hd[i] = 0; for (i = 0; i < gnv; ++i) { for (j = gv[i]; j < gv[i]+gd[i]-1; ++j) for (k = j+1; k < gv[i]+gd[i]; ++k) { v = eno[j]; w = eno[k]; he[hv[v]+(hd[v]++)] = w; he[hv[w]+(hd[w]++)] = v; } } }