void dependency_tree::strong_connect( dependency_node *dnode )
{
    dnode->index = open_index;
    dnode->lowlink = open_index;
    ++open_index;
    connection_stack.push( dnode );
    dnode->on_stack = true;

    for( std::vector<dependency_node *>::iterator it = dnode->parents.begin();
         it != dnode->parents.end(); ++it ) {
        if( ( *it )->index < 0 ) {
            strong_connect( *it );
            dnode->lowlink = std::min( dnode->lowlink, ( *it )->lowlink );
        } else if( ( *it )->on_stack ) {
            dnode->lowlink = std::min( dnode->lowlink, ( *it )->index );
        }
    }

    if( dnode->lowlink == dnode->index ) {
        std::vector<dependency_node *> scc;

        dependency_node *d;
        do {
            d = connection_stack.top();
            scc.push_back( d );
            connection_stack.pop();
            d->on_stack = false;
        } while( dnode->key != d->key );

        strongly_connected_components.push_back( scc );
        dnode->on_stack = false;
    }
}
// makes sure to set up Cycle errors properly!
void dependency_tree::check_for_strongly_connected_components()
{
    strongly_connected_components = std::vector<std::vector<dependency_node * > >();
    open_index = 0;
    connection_stack = std::stack<dependency_node *>();

    for( auto &elem : master_node_map ) {
        //nodes_on_stack = std::vector<dependency_node*>();
        // clear it for the next stack to run
        if( elem.second.index < 0 ) {
            strong_connect( &elem.second );
        }
    }

    // now go through and make a set of these
    std::set<dependency_node *> in_circular_connection;
    for( auto &elem : strongly_connected_components ) {
        if( elem.size() > 1 ) {
            for( auto &elem_node : elem ) {
                DebugLog( D_PEDANTIC_INFO, DC_ALL ) << "--" << elem_node->key.str() << "\n";
                in_circular_connection.insert( elem_node );
            }

        }
    }
    // now go back through this and give them all the circular error code!
    for( const auto &elem : in_circular_connection ) {
        ( elem )->all_errors[CYCLIC].push_back( "In Circular Dependency Cycle" );
    }
}
// makes sure to set up Cycle errors properly!
void dependency_tree::check_for_strongly_connected_components()
{
    strongly_connected_components = std::vector<std::vector<dependency_node * > >();
    open_index = 0;
    connection_stack = std::stack<dependency_node *>();

    for (std::map<std::string, dependency_node *>::iterator g = master_node_map.begin();
         g != master_node_map.end(); ++g) {
        //nodes_on_stack = std::vector<dependency_node*>();
        // clear it for the next stack to run
        if (g->second->index < 0) {
            strong_connect(g->second);
        }
    }

    // now go through and make a set of these
    std::set<dependency_node *> in_circular_connection;
    for (std::vector<std::vector<dependency_node *> >::iterator it =
             strongly_connected_components.begin();
         it != strongly_connected_components.end(); ++it) {
        if (it->size() > 1) {
            for (std::vector<dependency_node *>::iterator node = it->begin();
                 node != it->end(); ++node) {
                DebugLog( D_PEDANTIC_INFO, DC_ALL ) << "--" << (*node)->key << "\n";
                in_circular_connection.insert(*node);
            }

        }
    }
    // now go back through this and give them all the circular error code!
    for (std::set<dependency_node *>::iterator it = in_circular_connection.begin();
         it != in_circular_connection.end(); ++it) {
        (*it)->all_errors[CYCLIC].push_back("In Circular Dependency Cycle");
    }
}
void dependency_tree::strong_connect(dependency_node *dnode)
{
    dnode->index = open_index;
    dnode->lowlink = open_index;
    ++open_index;
    connection_stack.push(dnode);
    dnode->on_stack = true;

    for (int i = 0; i < dnode->parents.size(); ++i) {
        if (dnode->parents[i]->index < 0) {
            strong_connect(dnode->parents[i]);
            dnode->lowlink = std::min(dnode->lowlink, dnode->parents[i]->lowlink);
        } else if (dnode->parents[i]->on_stack) {
            dnode->lowlink = std::min(dnode->lowlink, dnode->parents[i]->index);
        }
    }

    if (dnode->lowlink == dnode->index) {
        std::vector<dependency_node *> scc;

        dependency_node *d;
        do {
            d = connection_stack.top();
            scc.push_back(d);
            connection_stack.pop();
            d->on_stack = false;
        } while (dnode->key != d->key);

        strongly_connected_components.push_back(scc);
        dnode->on_stack = false;
    }
}
void strong_connect(const weighted_graf_t& graph, std::vector<std::vector<int>>& components,
                    std::vector<int>& index, std::vector<int>& lowlink,
                    std::vector<int>& stack, int ind, int v) {
    index[v] = ind;
    lowlink[v] = ind;
    ind++;
    stack.push_back(v);

    for (const auto& edge : graph[v]) {
        int w = edge.first;
        if (index[w] == 0) {
            strong_connect(graph, components, index, lowlink, stack, ind, w);
            lowlink[v] = std::min(lowlink[v], lowlink[w]);
        } else if (index[w] != -1) {
            lowlink[v] = std::min(lowlink[v], index[w]);
        }
    }
    if (lowlink[v] == index[v]) {  // v is root node
        std::vector<int> component;
        int w;
        do {
            w = stack.back();
            stack.pop_back();
            component.push_back(w);
            index[w] = -1;
        } while (w != v);
        components.push_back(component);
    }
}
std::vector<std::vector<int>> strongly_connected_components(const weighted_graf_t& graph) {
    int n = graph.size(), ind = 0;
    std::vector<int> index(n, 0), lowlink(n, 0), stack;
    std::vector<std::vector<int>> components;
    for (int i = 0; i < n; ++i) {
        if (index[i] == 0) strong_connect(graph, components, index, lowlink, stack, ind, i);
    }
    return components;
}