/******************************************************************** _ColorVertices_HideEdge() An overload to perform the degree list updates for the edge endpoints. This routine also covers the work done by _HideVertex() and part of the work done by _ContractEdge() and _IdentifyVertices(). ********************************************************************/ void _ColorVertices_HideEdge(graphP theGraph, int e) { ColorVerticesContext *context = (ColorVerticesContext *) gp_GetExtension(theGraph, COLORVERTICES_ID); if (context != NULL) { int u, v, udeg, vdeg; // Get the endpoint vertices of the edge u = theGraph->G[e].v; v = theGraph->G[gp_GetTwinArc(theGraph, e)].v; // Get the degrees of the vertices udeg = _GetVertexDegree(context, u); vdeg = _GetVertexDegree(context, v); // Remove them from the degree lists that contain them _RemoveVertexFromDegList(context, theGraph, u, udeg); _RemoveVertexFromDegList(context, theGraph, v, vdeg); // Hide the edge context->functions.fpHideEdge(theGraph, e); // Decrement the degrees of the endpoint vertices udeg--; vdeg--; // Add them to the new degree lists _AddVertexToDegList(context, theGraph, u, udeg); _AddVertexToDegList(context, theGraph, v, vdeg); } }
int _ColorVertices_IdentifyVertices(graphP theGraph, int u, int v, int eBefore) { ColorVerticesContext *context = (ColorVerticesContext *) gp_GetExtension(theGraph, COLORVERTICES_ID); if (context != NULL) { int e_v_last, e_v_first; // First, identify u and v. No point in taking v's degree beforehand // because some of its incident edges may indicate neighbors of u. This // causes v to be moved to a lower degree list than deg(v). if (context->functions.fpIdentifyVertices(theGraph, u, v, eBefore) != OK) return NOTOK; // The edges transferred from v to u are indicated on the top of the // stack, which looks like this after identifying u and v: // ... e_u_succ e_v_last e_v_first e_u_pred u v e_v_first = sp_Get(theGraph->theStack, sp_GetCurrentSize(theGraph->theStack)-4); e_v_last = sp_Get(theGraph->theStack, sp_GetCurrentSize(theGraph->theStack)-5); // We count the number of edges K transferred from v to u after the // common edges were hidden if (gp_IsArc(theGraph, e_v_first)) { int J, K, degu; for (J=e_v_first, K=1; J != e_v_last; J=gp_GetNextArc(theGraph, J)) K++; // Remove v from the degree list K. During IdentifyVertices(), if v had any // common edges with u, they were "hidden", which reduced the degree of v to K. _RemoveVertexFromDegList(context, theGraph, v, K); // We move u from degree list deg(u)-K to degree list deg(u) degu = gp_GetVertexDegree(theGraph, u); _RemoveVertexFromDegList(context, theGraph, u, degu-K); _AddVertexToDegList(context, theGraph, u, degu); } return OK; } return NOTOK; }
int gp_ColorVertices(graphP theGraph) { ColorVerticesContext *context = NULL; int v, deg; int u=0, w=0, contractible; // Attach the algorithm if it is not already attached if (gp_AttachColorVertices(theGraph) != OK) return NOTOK; // Ensure there is enough stack to perform this operation. // At a maximum, the graph reduction will push 7N+M integers. // One integer is pushed per edge that is hidden. Plus, whether // a vertex is hidden or identified with another vertex, 7 integers // are used to store enough information to restore it. if (sp_NonEmpty(theGraph->theStack)) return NOTOK; if (sp_GetCapacity(theGraph->theStack) < 7*theGraph->N + theGraph->M) { stackP newStack = sp_New(7*theGraph->N + theGraph->M); if (newStack == NULL) return NOTOK; sp_Free(&theGraph->theStack); theGraph->theStack = newStack; } // Get the extension context and reinitialize it if necessary gp_FindExtension(theGraph, COLORVERTICES_ID, (void *)&context); if (context->color[0] > -1) _ColorVertices_Reinitialize(context); // Initialize the degree lists, and provide a color for any trivial vertices for (v = 0; v < theGraph->N; v++) { deg = gp_GetVertexDegree(theGraph, v); _AddVertexToDegList(context, theGraph, v, deg); if (deg == 0) context->color[v] = 0; } // Initialize the visited flags so they can be used during reductions _FillVisitedFlags(theGraph, 0); // Reduce the graph using minimum degree selection while (context->numVerticesToReduce > 0) { v = _GetVertexToReduce(context, theGraph); // Find out if v is contractible and the neighbors to contract contractible = _GetContractibleNeighbors(context, v, &u, &w); // Remove the vertex from the graph. This calls the fpHideEdge // overload, which performs the correct _RemoveVertexFromDegList() // and _AddVertexToDegList() operations on v and its neighbors. if (gp_HideVertex(theGraph, v) != OK) return NOTOK; // If v was contractibile, then identify u and w if (contractible) { if (gp_IdentifyVertices(theGraph, u, w, NIL) != OK) return NOTOK; } } // Restore the graph one vertex at a time, coloring each vertex distinctly // from its neighbors as it is restored. context->colorDetector = (int *) calloc(theGraph->N, sizeof(int)); if (context->colorDetector == NULL) return NOTOK; if (gp_RestoreVertices(theGraph) != OK) return NOTOK; free(context->colorDetector); context->colorDetector = NULL; return OK; }