
Untitled
By: a guest on
Mar 13th, 2011 | syntax:
None | size: 1.55 KB | hits: 75 | expires: Never
#!/usr/bin/perl
# Code assumes input graph is a binary tree as stated in
# the problem, NOT a binary *search* tree. Requres log n
# time and space, where n is the number of nodes in the tree.
#
# Example to compute LCA(3,6) in the tree in the diagram:
# perl lca '8: 3 10; 3: 1 6; 6: 4 7; 10: 14; 14: 13' 3 6
use strict;
use warnings;
my($rawtree, $node1, $node2) = @ARGV;
print "LCA($node1, $node2) = ",
LeastCommonAncestor(InvertGraph(ParseGraph($rawtree)), $node1, $node2);
sub LeastCommonAncestor {
my ($invertedtree, $node1, $node2) = @_;
my %parentsofnode1 = map { $_ => 1 } Descendants($invertedtree, $node1);
foreach my $parentofnode2 (Descendants($invertedtree, $node2)) {
if ($parentsofnode1{$parentofnode2}) {
return $parentofnode2;
}
}
die "can't happen in a tree\n";
}
sub ParseGraph {
my ($rawgraph) = @_;
my %graph;
foreach (split /\s*;\s*/, $rawgraph) {
my ($node, $successors) = /^\s*([^:\s]*):\s*(.*)/;
$node =~ s/^\s+//;
$graph{$node} = { map { $_ => 1 } split /\s+/, $successors };
}
return \%graph;
}
sub InvertGraph {
my ($graph) = @_;
my %invertedgraph;
foreach my $src (keys %$graph) {
foreach my $dst (keys %{ $graph->{$src} }) {
$invertedgraph{$dst}{$src} = 1;
}
}
return \%invertedgraph;
}
sub Descendants {
my ($dag, $node) = @_;
return (
$node,
map { Descendants($dag, $_) } Successors($dag, $node),
);
}
sub Successors {
my ($graph, $node) = @_;
return keys %{ $graph->{$node} };
}