tarjan.cc revision 161c4a132743f15fc4757112b673085c2a7a7f29
1// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4#include "update_engine/payload_generator/tarjan.h" 5 6#include <algorithm> 7#include <vector> 8 9#include <base/logging.h> 10 11#include "update_engine/utils.h" 12 13using std::min; 14using std::vector; 15 16namespace chromeos_update_engine { 17 18namespace { 19const vector<Vertex>::size_type kInvalidIndex = -1; 20} 21 22void TarjanAlgorithm::Execute(Vertex::Index vertex, 23 Graph* graph, 24 vector<Vertex::Index>* out) { 25 stack_.clear(); 26 components_.clear(); 27 index_ = 0; 28 for (Graph::iterator it = graph->begin(); it != graph->end(); ++it) 29 it->index = it->lowlink = kInvalidIndex; 30 required_vertex_ = vertex; 31 32 Tarjan(vertex, graph); 33 if (!components_.empty()) 34 out->swap(components_[0]); 35} 36 37void TarjanAlgorithm::Tarjan(Vertex::Index vertex, Graph* graph) { 38 CHECK_EQ((*graph)[vertex].index, kInvalidIndex); 39 (*graph)[vertex].index = index_; 40 (*graph)[vertex].lowlink = index_; 41 index_++; 42 stack_.push_back(vertex); 43 for (Vertex::EdgeMap::iterator it = (*graph)[vertex].out_edges.begin(); 44 it != (*graph)[vertex].out_edges.end(); ++it) { 45 Vertex::Index vertex_next = it->first; 46 if ((*graph)[vertex_next].index == kInvalidIndex) { 47 Tarjan(vertex_next, graph); 48 (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink, 49 (*graph)[vertex_next].lowlink); 50 } else if (utils::VectorContainsValue(stack_, vertex_next)) { 51 (*graph)[vertex].lowlink = min((*graph)[vertex].lowlink, 52 (*graph)[vertex_next].index); 53 } 54 } 55 if ((*graph)[vertex].lowlink == (*graph)[vertex].index) { 56 vector<Vertex::Index> component; 57 Vertex::Index other_vertex; 58 do { 59 other_vertex = stack_.back(); 60 stack_.pop_back(); 61 component.push_back(other_vertex); 62 } while (other_vertex != vertex && !stack_.empty()); 63 64 if (utils::VectorContainsValue(component, required_vertex_)) { 65 components_.resize(components_.size() + 1); 66 component.swap(components_.back()); 67 } 68 } 69} 70 71} // namespace chromeos_update_engine 72