/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

// -*- C++ -*-
//==========================================================================
//
//   connectivity.h
//
//==========================================================================

#ifndef GTL_CONNECTIVITY_H
#define GTL_CONNECTIVITY_H

#include <GTL/GTL.h>
#include <GTL/dfs.h>
#include <vector>

__GTL_BEGIN_NAMESPACE

/**
 * @short Connected components
 *
 * Find all of the connected components in an undirected graph.
 * Obviously there is a close relationship between DFS and the finding
 * of connected components.  Thus this test takes advantage of the
 * possibility to add pieces of code to the DFS-class in order to
 * label the nodes according to their component-number.
 */

class connectivity : public dfs 
{
public:
    connectivity ();
    virtual ~connectivity () {}
    
    /**
     * Necessary preconditions:
     * <ul>
     * <li> <code>G</code> is undirected.
     * <li> DFS may be applied 
     * </ul>
     * 
     * @param <code>G</code> graph.
     * @return <code>algorithm::GTL_OK</code> if connected component search can
     * be applied to <code>G</code>.
     */
    virtual int check (graph& G);
    
    
    /**
     * Reset
     */
    virtual void reset ();
    
    
    /**
     * Number of components in graph.
     * 
     * @return the number of components in the graph.
     */
    int number_of_components () const
	{return component_count;}
    
    
    /**
     * Component number of a node of the graph.
     * 
     * @return the component number of node n.
     */
    
    int component_num (const node& n) const
	{return component_nums[n];}
    
    
    /**
     * @internal
     */
    typedef list<node>::const_iterator component_iterator;
    
    /**
     * Start iteration over nodes of k-th connected component.
     * 
     * @return iterator to k-th component.
     */
    component_iterator component_begin (int k) const
	{ return component_lists[k].begin(); }
    
    /**
     * End of iteration over nodes of k-th connected component.
     * 
     * @return iterator to one-past-the-end of k-th component.
     */
    component_iterator component_end (int k) const
	{ return component_lists[k].end(); }
    
    
    //-----------------------------------------------------------------------
    //   Handler used to extend dfs to components
    //-----------------------------------------------------------------------
    /**
     * @internal
     */
    virtual void init_handler (graph&);
    
    /**
     * @internal
     */
    virtual void entry_handler (graph&, node&, node&);
    
    /**
     * @internal
     */
    virtual void new_start_handler (graph&, node&);    
    
protected:
    /**
     * @internal
     */
    int component_count;
    /**
     * @internal
     */
    node_map<int> component_nums;
    /**
     * @internal
     */
    vector<list<node> > component_lists;
};

__GTL_END_NAMESPACE

#endif // GTL_CONNECTIVITY_H

//--------------------------------------------------------------------------
//   end of file
//--------------------------------------------------------------------------

