/* * Returns the active c-node of RBC list containing "u". * Traverses only nodes with label_b <= dfspos_num[w]. * Let z be the first element of RBC. * All traversed nodes, but z, are inserted in "nl". * Pre-conditions: * - "u" is not the 1st element in RBC list; * - ptritem[u] is the pointer to the item containing "u"; * - "u" is a node that is an ancestor of a neighbor of w; * - state[v] == NOT_VISITED for each node v in RBC list that was not * traversed. */ node PlanarityTestImpl::findActiveCNode(node u, node w, list<node> &nl) { list<node> traversedNodesInRBC; assert(isCNode(parent.get(u.id))); if (state.get(u.id) != NOT_VISITED) { assert(!isCNode(parent.get(parent.get(u.id).id))); return parent.get(u.id); } BmdLink<node> *it1 = ptrItem.get(u.id); // ptrItem[u]; assert(it1 != nullptr); state.set(u.id, VISITED_IN_RBC); traversedNodesInRBC.push_back(u); BmdLink<node> *it = searchRBC(1, it1, w, traversedNodesInRBC); if (it == nullptr) it = searchRBC(0, it1, w, traversedNodesInRBC); assert(it != nullptr); node v = it->getData(); node cNode; if (it->prev() != nullptr && it->succ() != nullptr) cNode = parent.get(v.id); // path compressed; else cNode = activeCNode[it]; assert(cNode != NULL_NODE); node first = RBC[cNode].firstItem()->getData(); // path compression; // forall(v, traversedNodesInRBC) for (list<node>::iterator it = traversedNodesInRBC.begin(); it != traversedNodesInRBC.end(); ++it) { if (*it != first) { if (*it != u) nl.push_back(v); parent.set((*it).id, cNode); } else state.set((*it).id, NOT_VISITED); } return cNode; }
//================================================================= BmdLink<node> *PlanarityTestImpl::searchRBC(int dir, BmdLink<node> *it, node n, list<node> &traversedNodesInRBC) { if (it != nullptr && (it->prev() == nullptr || it->succ() == nullptr)) // 1st or last item in RBC; return it; BmdLink<node> *prev = it; BmdLink<node> *aux1 = it->prev(); BmdLink<node> *aux2 = it->succ(); if (dir == 1) { // leda_swap(aux1, aux2); BmdLink<node> *tmp = aux1; aux1 = aux2; aux2 = tmp; } it = aux1; node u = it->getData(); int b = labelB.get(u.id); while (it != nullptr && (b <= dfsPosNum.get(n.id) || dir != 1) && state.get(u.id) == NOT_VISITED) { aux1 = it->prev(); if (aux1 == prev) aux1 = it->succ(); prev = it; it = aux1; u = prev->getData(); state.set(u.id, VISITED_IN_RBC); traversedNodesInRBC.push_back(u); if (it != nullptr) { u = it->getData(); b = labelB.get(u.id); } } if (it == nullptr) return prev; else if (state.get(u.id) != NOT_VISITED || (it->prev() == nullptr || it->succ() == nullptr)) return it; else return nullptr; }
//================================================================= void PlanarityTestImpl::addOldCNodeRBCToNewRBC(node oldCNode, node, node n, node n1, node n2, tlp::BmdList<node> &nodeList) { // compress RBC[oldCNode]: // removes all nodes v in RBC[oldCNode] s.t. label_b[v] < dfspos_num[n] // or v = parent[oldCNode]. BmdLink<node> *firstItem = RBC[oldCNode].firstItem(); BmdLink<node> *predItem = RBC[oldCNode].cyclicPred(firstItem, nullptr); BmdLink<node> *succItem = RBC[oldCNode].cyclicSucc(firstItem, nullptr); node predNode = predItem->getData(); node succNode = succItem->getData(); node ul; node ur; // goes to the left; while (labelB.get(predNode.id) == dfsPosNum.get(n.id) && predNode != n1 && predNode != n2) { if (!ul.isValid()) ul = predNode; BmdLink<node> *tmp = predItem; predItem = RBC[oldCNode].cyclicPred(predItem, firstItem); predNode = predItem->getData(); RBC[oldCNode].delItem(tmp); } // goes to right; while (labelB.get(succNode.id) == dfsPosNum.get(n.id) && succNode != n1 && succNode != n2) { if (!ur.isValid()) ur = succNode; BmdLink<node> *tmp = succItem; succItem = RBC[oldCNode].cyclicSucc(succItem, firstItem); succNode = succItem->getData(); RBC[oldCNode].delItem(tmp); } RBC[oldCNode].delItem(RBC[oldCNode].firstItem()); // endpoint to correctly concatentates with RBC[new_cnode]; node first = n1; if (!n1.isValid()) { if (ul.isValid()) first = predNode; else first = succNode; } // note that oldCNode may have flipped; if (RBC[oldCNode].lastItem()->getData() == first) RBC[oldCNode].reverse(); // reoves n1 and n2 from RBC[oldCNode]; if (n1.isValid()) { RBC[oldCNode].delItem(RBC[oldCNode].firstItem()); } if (n2.isValid()) { RBC[oldCNode].delItem(RBC[oldCNode].lastItem()); } nodeList.conc(RBC[oldCNode]); }
/* * Moves embedding of oldCNode to embList - note that oldCNode may * flip - and embeds all edges in path from w (starting with a back-edge from w) and * ending in a node in RBC[oldCNode]. * All representants to be embedded later is ordered and inserted in toEmbedLater. * emb_back_edges_out_w is false only in case of 2 terminal * nodes, for one of the two terminals (see calculate_partial_embedding). * Preconditions: * - for a back-edge e, if u is representant of source(e) and u in RBC[oldCNode], * then e is in list b_edges_repres[u]; * - the first element in list RBC[oldCNode] is parent[oldCNode]; * - if u != nil then u is a node in RBC[oldCNode] s.t. label_b[u] > dfspos_num[w] * and there exists a path from u to w that doesn't contain any node in the * 2-connected component represented by oldCNode, except u. */ void PlanarityTestImpl::addOldCNodeToEmbedding(bool embBackEdgesOutW, Graph *sG, node w, node oldCNode, node u, map<node, list<edge> >& bEdgesRepres, list<node>& traversedNodes, list<node>& toEmbedLater, tlp::BmdList<edge>& embList) { BmdLink<node> *it = RBC[oldCNode].firstItem(); BmdLink<node> *itl = RBC[oldCNode].cyclicPred(it, 0); BmdLink<node> *itr = RBC[oldCNode].cyclicSucc(it, 0); node jl = itl->getData(); node jr = itr->getData(); list<node> listNodesL, listNodesR; // goes to the left; BmdLink<node> *aux = NULL; BmdLink<node> *s = it; while (labelB.get(jl.id) <= dfsPosNum.get(w.id)) { assert(jl != u); if (labelB.get(jl.id) == dfsPosNum.get(w.id)) listNodesL.push_back(jl); aux = itl; itl = RBC[oldCNode].cyclicPred(itl, s); s = aux; jl = itl->getData(); } // goes to the right; BmdLink<node> *p = it; while (labelB.get(jr.id) <= dfsPosNum.get(w.id)) { assert(jr != u); if (labelB.get(jr.id) == dfsPosNum.get(w.id)) listNodesR.push_back(jr); aux = itr; itr = RBC[oldCNode].cyclicSucc(itr, p); p = aux; jr = itr->getData(); } // checks if need to flip oldCNode; // u == nil when oldCNode is a terminal node; bool flipped = ((!listNodesL.empty() && (jl == u || u == NULL_NODE)) || (jr != u && u != NULL_NODE)); if (flipped) listNodesL.swap(listNodesR); // embeds all back-edges in oldCNode; // listNodesR.reverse_items(); listNodesR.reverse(); node t; //forall(t, listNodesR) for (list<node>::iterator it = listNodesR.begin() ; it != listNodesR.end() ; it++) { t = *it; embedBackEdges(embBackEdgesOutW, sG, t, traversedNodes, bEdgesRepres[t], embList); } if (flipped) embedList[oldCNode].reverse(); embedList[oldCNode].conc(embList); embedList[oldCNode].swap(embList); //toEmbedLater.conc(listNodesL, LEDA::before); toEmbedLater.splice(toEmbedLater.begin(), listNodesL); }