int  _getImageVertices(graphP theGraph, int *degrees, int maxDegree,
                       int *imageVerts, int maxNumImageVerts)
{
int K, v, imageVertPos, degree;

     for (degree = 0; degree <= maxDegree; degree++)
          degrees[degree] = 0;

     for (K = 0; K < maxNumImageVerts; K++)
          imageVerts[K] = NIL;

     imageVertPos = 0;

     for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
     {
          degree = gp_GetVertexDegree(theGraph, v);
          if (degree == 1)
              return NOTOK;
          if (degree > maxDegree)
              return NOTOK;

          degrees[degree]++;

          if (imageVertPos < maxNumImageVerts && degree > 2)
              imageVerts[imageVertPos++] = v;
          else if (degree > 2)
              return NOTOK;
     }

     return OK;
}
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;
}
Beispiel #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;
}
int  _CheckEmbeddingFacialIntegrity(graphP theGraph)
{
stackP theStack = theGraph->theStack;
int EsizeOccupied, v, e, eTwin, eStart, eNext, NumFaces, connectedComponents;

     if (theGraph == NULL)
         return NOTOK;

/* The stack need only contain 2M entries, one for each edge record. With
        max M at 3N, this amounts to 6N integers of space.  The embedding
        structure already contains this stack, so we just make sure it
        starts out empty. */

     sp_ClearStack(theStack);

/* Push all arcs and set them to unvisited */

	 EsizeOccupied = gp_EdgeInUseIndexBound(theGraph);
     for (e = gp_GetFirstEdge(theGraph); e < EsizeOccupied; e+=2)
     {
    	  // Except skip edge holes
          if (gp_EdgeInUse(theGraph, e))
          {
			  sp_Push(theStack, e);
			  gp_ClearEdgeVisited(theGraph, e);
			  eTwin = gp_GetTwinArc(theGraph, e);
			  sp_Push(theStack, eTwin);
			  gp_ClearEdgeVisited(theGraph, eTwin);
          }
     }

     // There are M edges, so we better have pushed 2M arcs just now
     // i.e. testing that the continue above skipped only edge holes
     if (sp_GetCurrentSize(theStack) != 2*theGraph->M)
    	 return NOTOK;


/* Read faces until every arc is used */

     NumFaces = 0;
     while (sp_NonEmpty(theStack))
     {
            /* Get an arc; if it has already been used by a face, then
                don't use it to traverse a new face */
            sp_Pop(theStack, eStart);
            if (gp_GetEdgeVisited(theGraph, eStart)) continue;

            e = eStart;
            do {
                eNext = gp_GetNextArcCircular(theGraph, gp_GetTwinArc(theGraph, e));
                if (gp_GetEdgeVisited(theGraph, eNext))
                    return NOTOK;
                gp_SetEdgeVisited(theGraph, eNext);
                e = eNext;
            } while (e != eStart);
            NumFaces++;
     }

/* Count the external face once rather than once per connected component;
    each connected component is detected by the fact that it has no
    DFS parent, except in the case of isolated vertices, no face was counted
    so we do not subtract one. */

     connectedComponents = 0;
     for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
     {
          if (gp_IsDFSTreeRoot(theGraph, v))
          {
              if (gp_GetVertexDegree(theGraph, v) > 0)
                  NumFaces--;
              connectedComponents++;
          }
     }

     NumFaces++;

/* Test number of faces using the extended Euler's formula.
     For connected components, Euler's formula is f=m-n+2, but
     for disconnected graphs it is extended to f=m-n+1+c where
     c is the number of connected components.*/

     return NumFaces == theGraph->M - theGraph->N + 1 + connectedComponents
            ? OK : NOTOK;
}