I had a couple of minutes, so here is a solution based on
blokhead's ideas using
Graph
use strict;
use warnings;
use Graph::Directed;
my $g = Graph::Directed->new();
$/ = ""; # paragraph mode
while (<DATA>) {
my @verts = split "\n", $_;
my $old_vertex = undef;
# add vertices and edges
for my $v (@verts) {
$g->add_vertex($v) unless $g->has_vertex($v);
$g->add_edge( $old_vertex, $v ) if defined $old_vertex;
$old_vertex = $v;
}
}
# determine root of tree
my $root;
for ( $g->vertices() ) {
if ( $g->is_source_vertex($_) ) {
warn "more than one root: $root $_\n" if defined $root;
$root = $_;
}
}
die "$g has cycle\n" if $g->has_a_cycle();
# number vertices recursively, starting with 0 at $root
my %vert_num;
sub number
{
my ($v, $i) = @_;
if (exists $vert_num{$v}) {
$vert_num{$v} = $i if $vert_num{$v} < $i;
} else {
$vert_num{$v} = $i;
}
for my $s ($g->successors($v)) {
number($s, $i+1);
}
}
number($root, 0);
{
my %h;
@h{values %vert_num} = ();
warn "ordering cannot be determined\n"
if (scalar values %vert_num) != (scalar values %h);
}
say sprintf("%10s: %2d",$_, $vert_num{$_})
for sort { $vert_num{$a} <=> $vert_num{$b} } keys %vert_num;
__DATA__
Alpha
Beta
Epsilon
Zeta
Beta
Gamma
Zeta
Alpha
Gamma
Delta
Epsilon
which prints
Alpha: 0
Beta: 1
Gamma: 2
Delta: 3
Epsilon: 4
Zeta: 5
and dies over 'cycles' and warns about 'indetermined order' - if necessary.