use strict;
use warnings;
use constant True => 1;

sub add_edge {
    my ($g, $a, $b, $weight) = @_;
    $g->{$a} ||= {name => $a};
    $g->{$b} ||= {name => $b};
    push @{$g->{$a}{edges}}, {weight => $weight, vertex => $g->{$b}};
}

sub push_priority {
    my ($a, $v) = @_;
    my $i = 0;
    my $j = $
    while ($i <= $j) {
        my $k = int(($i + $j) / 2);
        if ($a->[$k]{dist} >= $v->{dist}) { $j = $k - 1 }
        else                              { $i = $k + 1 }
    }
    splice @$a, $i, 0, $v;
}

sub dijkstra {
    my ($g, $a, $b) = @_;
    for my $v (values %$g) {
        $v->{dist} = 10e7; 
        delete @$v{'prev', 'visited'}
     }
    $g->{$a}{dist} = 0;
    my $h = [];
    push_priority($h, $g->{$a});
    while () {
        my $v = shift @$h;
        last if !$v or $v->{name} eq $b;
        $v->{visited} = True;
        for my $e (@{$v->{edges}}) {
            my $u = $e->{vertex};
            if (!$u->{visited} && $v->{dist} + $e->{weight} <= $u->{dist}) {
                $u->{prev} = $v;
                $u->{dist} = $v->{dist} + $e->{weight};
                push_priority($h, $u);
            }
        }
    }
}

my $g = {};
add_edge($g, @$_) for
 (['a', 'b',  7], ['a', 'c',  9], ['a', 'f', 14],
  ['b', 'c', 10], ['b', 'd', 15], ['c', 'd', 11],
  ['c', 'f',  2], ['d', 'e',  6], ['e', 'f',  9]);

dijkstra($g, 'a', 'e');

my $v = $g->{e};
my @a;
while ($v) {
    push @a, $v->{name};
    $v = $v->{prev};
}
my $path = join '', reverse @a;
print "$g->{e}{dist} $path\n";