示例#1
0
int  _MarkPathAlongBicompExtFace(graphP theGraph, int startVert, int endVert)
{
    int  Z, ZPrevLink, ZPrevArc;

    /* Mark the start vertex (and if it is a root copy, mark the parent copy too. */

    gp_SetVertexVisited(theGraph, startVert);

    /* For each vertex visited after the start vertex, mark the vertex and the
            edge used to get there.  Stop after marking the ending vertex. */

    Z = startVert;
    ZPrevLink = 1;
    do {
        Z = _GetNeighborOnExtFace(theGraph, Z, &ZPrevLink);

        ZPrevArc = gp_GetArc(theGraph, Z, ZPrevLink);

        gp_SetEdgeVisited(theGraph, ZPrevArc);
        gp_SetEdgeVisited(theGraph, gp_GetTwinArc(theGraph, ZPrevArc));
        gp_SetVertexVisited(theGraph, Z);

    } while (Z != endVert);

    return OK;
}
示例#2
0
/****************************************************************************
 _MarkDFSPath()

 Sets visited flags of vertices and edges from descendant to ancestor,
 including root copy vertices, and including the step of hopping from
 a root copy to its parent copy.

 At each vertex, the edge record is obtained whose type indicates that it
 leads to the DFS parent.  An earlier implementation just used the DFS parent
 member of the vertex, but then had to find the edge to mark anyway.
 This method is more generalized because some extension algorithms reduce
 DFS paths to single DFS tree edges, in which case the edge record with type
 EDGE_TYPE_PARENT may indicate the DFS paent or an ancestor.
 ****************************************************************************/
int  _MarkDFSPath(graphP theGraph, int ancestor, int descendant)
{
    int  e, parent;

    // If we are marking from a root (virtual) vertex upward, then go up to the parent
    // copy before starting the loop
    if (gp_IsVirtualVertex(theGraph, descendant))
        descendant = gp_GetPrimaryVertexFromRoot(theGraph, descendant);

    // Mark the lowest vertex (the one with the highest number).
    gp_SetVertexVisited(theGraph, descendant);

    // Mark all ancestors of the lowest vertex, and the edges used to reach
    // them, up to the given ancestor vertex.
    while (descendant != ancestor)
    {
        if (gp_IsNotVertex(descendant))
            return NOTOK;

        // If we are at a bicomp root, then ascend to its parent copy and
        // mark it as visited.
        if (gp_IsVirtualVertex(theGraph, descendant))
        {
            parent = gp_GetPrimaryVertexFromRoot(theGraph, descendant);
        }

        // If we are on a regular, non-virtual vertex then get the edge to the parent,
        // mark the edge, then fall through to the code that marks the parent vertex.
        else
        {
            // Scan the edges for the one marked as the DFS parent
            parent = NIL;
            e = gp_GetFirstArc(theGraph, descendant);
            while (gp_IsArc(e))
            {
                if (gp_GetEdgeType(theGraph, e) == EDGE_TYPE_PARENT)
                {
                    parent = gp_GetNeighbor(theGraph, e);
                    break;
                }
                e = gp_GetNextArc(theGraph, e);
            }

            // Sanity check on the data structure integrity
            if (gp_IsNotVertex(parent))
                return NOTOK;

            // Mark the edge
            gp_SetEdgeVisited(theGraph, e);
            gp_SetEdgeVisited(theGraph, gp_GetTwinArc(theGraph, e));
        }

        // Mark the parent, then hop to the parent and reiterate
        gp_SetVertexVisited(theGraph, parent);
        descendant = parent;
    }

    return OK;
}
void _MarkExternalFaceVertices(graphP theGraph, int startVertex)
{
    int nextVertex = startVertex;
    int e = gp_GetFirstArc(theGraph, nextVertex);
    int eTwin;

    // Handle the case of an isolated vertex
    if (gp_IsNotArc(e))
    {
    	gp_SetVertexVisited(theGraph, startVertex);
    	return;
    }

    // Process a non-trivial connected component
    do {
        gp_SetVertexVisited(theGraph, nextVertex);

        // The arc out of the vertex just visited points to the next vertex
        nextVertex = gp_GetNeighbor(theGraph, e);

        // Arc used to enter the next vertex is needed so we can get the
        // next edge in rotation order.
        // Note: for bicomps, first and last arcs of all external face vertices
        //       indicate the edges that hold them to the external face
        //       But _JoinBicomps() has already occurred, so cut vertices
        //       will have external face edges other than the first and last arcs
        //       Hence we need this more sophisticated traversal method
        eTwin = gp_GetTwinArc(theGraph, e);

        // Now we get the next arc in rotation order as the new arc out to the
        // vertex after nextVertex.  This sets us up for the next iteration.
        // Note: We cannot simply follow the chain of nextVertex first arcs
        //       as we started out doing at the top of this method.  This is
        //       because we are no longer dealing with bicomps only.
        //       Since _JoinBicomps() has already been invoked, there may now
        //       be cut vertices on the external face whose adjacency lists
        //       contain external face arcs in positions other than the first and
        //       and last arcs.  We will visit those vertices multiple times,
        //       which is OK (just that we have to explain why we're calculating
        //       jout in this way).
        e = gp_GetNextArcCircular(theGraph, eTwin);

        // Now things get really interesting.  The DFS root (startVertex) may
        // itself be a cut vertex to which multiple bicomps have been joined.
        // So we cannot simply stop when the external face walk gets back to
        // startVertex.  We must actually get back to startVertex using its
        // last arc.  This ensures that we've looped down into all the DFS
        // subtrees rooted at startVertex and walked their external faces.

        // Since we started the whole external face walk with the first arc
        // of startVertex, we need to proceed until we reenter startVertex
        // using its last arc.

    } while (eTwin != gp_GetLastArc(theGraph, startVertex));
}
示例#4
0
int _AddAndMarkEdge(graphP theGraph, int ancestor, int descendant)
{
    _AddBackEdge(theGraph, ancestor, descendant);

    /* Mark the edge so it is not deleted */

    gp_SetVertexVisited(theGraph, ancestor);
    gp_SetEdgeVisited(theGraph, gp_GetFirstArc(theGraph, ancestor));
    gp_SetEdgeVisited(theGraph, gp_GetFirstArc(theGraph, descendant));
    gp_SetVertexVisited(theGraph, descendant);

    return OK;
}
void _MarkPath(graphP theGraph, int e)
{
int  eTwin, nextVertex;

     nextVertex = gp_GetNeighbor(theGraph, e);
     // while nextVertex is strictly degree 2
     while (gp_IsArc(gp_GetFirstArc(theGraph, nextVertex)) &&
    		gp_IsArc(gp_GetLastArc(theGraph, nextVertex)) &&
    		gp_GetNextArc(theGraph, gp_GetFirstArc(theGraph, nextVertex)) == gp_GetLastArc(theGraph, nextVertex))
     {
         gp_SetVertexVisited(theGraph, nextVertex);

         eTwin = gp_GetTwinArc(theGraph, e);
         e = gp_GetFirstArc(theGraph, nextVertex);
         if (e == eTwin)
             e = gp_GetLastArc(theGraph, nextVertex);

         nextVertex = gp_GetNeighbor(theGraph, e);
     }
}
int  _TestSubgraph(graphP theSubgraph, graphP theGraph)
{
int v, e, degreeCount;
int Result = TRUE;
int invokeSortOnGraph = FALSE;
int invokeSortOnSubgraph = FALSE;

    // If the graph is not sorted by DFI, but the alleged subgraph is,
    // then "unsort" the alleged subgraph so both have the same vertex order
    if (!(theGraph->internalFlags & FLAGS_SORTEDBYDFI) &&
         (theSubgraph->internalFlags & FLAGS_SORTEDBYDFI))
    {
        invokeSortOnSubgraph = TRUE;
        gp_SortVertices(theSubgraph);
    }

    // If the graph is not sorted by DFI, but the alleged subgraph is,
    // then "unsort" the alleged subgraph so both have the same vertex order
    if (!(theSubgraph->internalFlags & FLAGS_SORTEDBYDFI) &&
         (theGraph->internalFlags & FLAGS_SORTEDBYDFI))
    {
        invokeSortOnGraph = TRUE;
        gp_SortVertices(theGraph);
    }

/* We clear all visitation flags */

     _ClearVertexVisitedFlags(theGraph, FALSE);

/* For each vertex... */
     for (v = gp_GetFirstVertex(theSubgraph), degreeCount = 0; gp_VertexInRange(theSubgraph, v); v++)
     {
          /* For each neighbor w in the adjacency list of vertex v in the
                subgraph, set the visited flag in w in the graph */

          e = gp_GetFirstArc(theSubgraph, v);
          while (gp_IsArc(e))
          {
        	  if (gp_IsNotVertex(gp_GetNeighbor(theSubgraph, e)))
        	  {
        		  Result = FALSE;
        		  break;
        	  }
        	  degreeCount++;
        	  gp_SetVertexVisited(theGraph, gp_GetNeighbor(theSubgraph, e));
              e = gp_GetNextArc(theSubgraph, e);
          }

          if (Result != TRUE)
        	  break;

          /* For each neighbor w in the adjacency list of vertex v in the graph,
                clear the visited flag in w in the graph */

          e = gp_GetFirstArc(theGraph, v);
          while (gp_IsArc(e))
          {
        	  if (gp_IsNotVertex(gp_GetNeighbor(theGraph, e)))
        	  {
        		  Result = FALSE;
        		  break;
        	  }
        	  gp_ClearVertexVisited(theGraph, gp_GetNeighbor(theGraph, e));
              e = gp_GetNextArc(theGraph, e);
          }

          if (Result != TRUE)
        	  break;

          /* For each neighbor w in the adjacency list of vertex v in the subgraph,
             ensure that the visited flag in w was cleared (otherwise, the "subgraph"
             would incorrectly contain an adjacency not contained in the ("super") graph) */

          e = gp_GetFirstArc(theSubgraph, v);
          while (gp_IsArc(e))
          {
              if (gp_GetVertexVisited(theGraph, gp_GetNeighbor(theSubgraph, e)))
              {
            	  Result = FALSE;
            	  break;
              }
              e = gp_GetNextArc(theSubgraph, e);
          }

          if (Result != TRUE)
        	  break;
     }

    // Restore the DFI sort order of either graph if it had to be reordered at the start
    if (invokeSortOnSubgraph)
        gp_SortVertices(theSubgraph);
    if (invokeSortOnGraph)
        gp_SortVertices(theGraph);

    // Assuming theSubgraph is a subgraph, we also do an extra integrity check to ensure
    // proper edge array utilization
    if (Result == TRUE)
    {
    	// If the edge count is wrong, we fail the subgraph test in a way that invokes
    	// the name NOTOK so that in debug mode there is more trace on the failure.
    	if (degreeCount != 2*theSubgraph->M)
    		Result = NOTOK == FALSE ? NOTOK : FALSE;
    }

     return Result;
}
int _TestForK23GraphObstruction(graphP theGraph, int *degrees, int *imageVerts)
{
int  v, e, imageVertPos;

     // This function operates over the imageVerts results produced by
     // getImageVertices, which only finds vertices of degree 3 or higher.
     // So, for a K2,3, there must be exactly two degree 3 vertices and
     // no degree 4 vertices.
     if (degrees[3] != 2)
         return FALSE;

     // For K_{2,3}, the three vertices of degree 2 were not
     // detected as image vertices because degree 2 vertices
     // are indistinguishable from the internal path vertices
     // between the image vertices.  So, here we acknowledge
     // that more image vertices need to be selected.
     imageVertPos = 2;

     // Assign the remaining three image vertices to be the
     // neighbors of the first degree 3 image vertex.
     // Ensure that each is distinct from the second
     // degree 3 image vertex. This must be the case because
     // the two degree 3 image vertices are in the same partition
     // and hence must not be adjacent.

     e = gp_GetFirstArc(theGraph, imageVerts[0]);
     while (gp_IsArc(e))
     {
         imageVerts[imageVertPos] = gp_GetNeighbor(theGraph, e);
         if (imageVerts[imageVertPos] == imageVerts[1])
             return FALSE;
         imageVertPos++;
         e = gp_GetNextArc(theGraph, e);
     }

     /* The paths from imageVerts[0] to each of the new degree 2
          image vertices are the edges we just traversed.
          Now test the paths between each of the degree 2 image
          vertices and imageVerts[1]. */

     _ClearVertexVisitedFlags(theGraph, FALSE);

     for (imageVertPos=2; imageVertPos<5; imageVertPos++)
     {
          if (_TestPath(theGraph, imageVerts[imageVertPos],
                                  imageVerts[1]) != TRUE)
              return FALSE;

          gp_SetVertexVisited(theGraph, imageVerts[imageVertPos]);
     }

     for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++)
          if (gp_GetVertexVisited(theGraph, v))
              degrees[2]--;

     /* If every degree 2 vertex is used in a path between the
          two degree 3 image vertices, then there are no extra
          pieces of the graph in theGraph.  Specifically, the
          prior tests identify a K_{2,3} and ensure that nothing
          else could exist in the graph... except extra degree 2
          vertices joined in a cycle. We return NOTOK in that case. */

     return degrees[2] == 0 ? TRUE : FALSE;
}