# This will be our transitive closure. my %is_winning_chain_over; my @new_relations; # First populate with the winners for my $team (keys %play_result) { while (my ($other_team, $won) = each %{$play_result{$team}}) { if ($won) { $is_winning_chain_over{$team}{$other_team} = 1; push @new_relations, [$team, $other_team]; } } } # Now compute the closure while (@new_relations) { my $relation = shift @new_relations; my ($winner, $loser) = @$relation; my $winner_is_over = $is_winning_chain_over{$winner}; my $loser_is_over = $is_winning_chain_over{$loser}; for my $third_team (keys %$loser_is_over) { if (not $winner_is_over->{$third_team}) { $winner_is_over{$third_team} = 1; push @new_relations, [$winner, $third_team]; } } }