Last time I needed to do this, which was a few years ago, I ended up rolling my own, because anything I could find in CPAN was too slow. This may have changed since then, but an algorithm for this is not difficult; see the attached code.

Here's a minimally tested implementation of classes Graph and Node to do what you want to do. At the end there's a short demo script.
use strict; use warnings; package Graph; sub new { my $self = bless +{}, shift; $self->build( @_ ); return $self; } sub build { my $self = shift; my ( $nodes, $edges ) = @_; sanity_check( $nodes, $edges ); my %nodes = map +( $_ => Node->new( $_ ) ), @$nodes; for my $edge ( @$edges ) { my @nodes = @nodes{ @$edge }; $nodes[ 0 ]->add_neighbor( $nodes[ 1 ] ); } $self->{ nodes } = \%nodes; return; } sub sanity_check { # just ensures that all edges refer to nodes in the given # node set; the graph may contain isolated nodes. my $nodes_hash = { map +( $_ => 1 ), @{ shift() } }; for my $edge ( @{ shift() } ) { defined $nodes_hash->{ $_ } || die "Unknown node: $_\n" for @$edge; } return; } sub connected_components { my $self = shift; my @components; my %visited; for my $node ( values %{ $self->{ nodes } } ) { next if defined $visited{ $node->{ id } }; push @components, $node->component; $visited{ $_ } = 1 for keys %{ $components[ -1 ] }; } return [ map [ keys %$_ ], @components ]; } package Node; sub new { my $self = bless +{}, shift; $self->{ id } = shift; return $self; } sub add_neighbor { my $self = shift; my $neighbor = shift; $self->{ neighbors }{ $neighbor->{ id } } = $neighbor; $neighbor->{ neighbors }{ $self->{ id } } = $self; return; } sub component { my $self = shift; my $component = shift || +{}; $component->{ $self->{ id } } = $self; for my $neighbor ( grep !defined $component->{ $_->{ id } }, values %{ $self->{ neighbors } } ) { $neighbor->component( $component ); } return $component; } package main; my $n_nodes = 25; my $max_edges = 15; my $r = sub { 1 + int(rand $n_nodes) }; my $nodes = [ 1..$n_nodes ]; my $edges = [ map [ $r->(), $r->() ], 1..$max_edges ]; print "@$_\n" for @{ Graph->new( $nodes, $edges )->connected_components() }; __END__ 6 11 7 17 8 4 1 18 21 15 19 16 2 22 25 23 5 10 13 3 9 12 20 14 24

the lowliest monk


In reply to Re: connected component by tlm
in thread connected component by water

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.