/********************************************************************
 _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;
}
Ejemplo n.º 3
0
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;
}