从根到树中叶子的预期最大路径长度

时间:2016-01-15 12:05:07

标签: algorithm math tree probability

假设我们有一棵树,每条边的长度为1或2,概率相等。从根到叶子的所有路径都包含相同数量的边。找到从根到叶子的预期最大路径长度。

树的例子

     *
    / \
   /   \
  *     *

预期最大路径长度为1/4 * 1 + 3/4 * 2 = 7/4,边缘长度为11,12,21,22,后三者为最大长度2,第一个 - 1。

2 个答案:

答案 0 :(得分:1)

这可以递归计算而不会有太多麻烦。

"""
A distribution is represented as a list of probabilities summing to one.
The probability of outcome i is the entry at position i (zero-based indexing).
"""


def max_distribution(dist1, dist2):
    """
    Given two distributions dist1, dist2, computes the distribution of
    the max of a sample from dist1 and a sample from dist2.
    """
    max_dist = []
    cum1 = 0
    cum2 = 0
    for i in range(max(len(dist1), len(dist2))):
        p1 = dist1[i] if i < len(dist1) else 0
        p2 = dist2[i] if i < len(dist2) else 0
        max_dist.append(cum1 * p2 + p1 * cum2 + p1 * p2)
        cum1 += p1
        cum2 += p2
    return max_dist


def distribution_plus_edge(dist):
    """
    Given a distribution dist, computes the distribution of
    a sample from dist plus an uniform random choice in {1, 2}.
    """
    dist_plus = [0] * (len(dist) + 2)
    for i in range(len(dist)):
        for j in [1, 2]:
            dist_plus[i + j] += 0.5 * dist[i]
    return dist_plus


def expectation(dist):
    """
    Given a distribution dist, returns the expectation.
    """
    return sum(i * p for i, p in enumerate(dist))


def max_path_length_distribution(tree):
    """
    Given a tree represented as a list of the root's subtrees,
    computes the distribution of max path lengths from the root to a leaf.
    """
    dist = [1]
    for child in tree:
        child_dist = distribution_plus_edge(max_path_length_distribution(child))
        dist = max_distribution(dist, child_dist)
    return dist


tree = [[], []]
print(expectation(max_path_length_distribution(tree)))  # 1.75
tree = [[[], []], []]
print(expectation(max_path_length_distribution(tree)))  # 3.25

答案 1 :(得分:0)

数据结构

class Tree
{
public:
    Tree() {}
    Tree(std::initializer_list<Tree> children) : m_children(children) {}
    Tree(std::vector<Tree> children) : m_children(children) {}

    const std::vector<Tree>& GetChildren() const { return m_children; }

private:
    std::vector<Tree> m_children;
};

算法

const int EdgeFirst = 1;
const int EdgeSecond = 2;

map<int, float> empl_internal(const Tree& t)
{
    map<int, float> prev;
    prev[0] = 1.f;

    for (const auto& c : t.GetChildren())
    {
        map<int, float> current;

        for (auto& lpFirst : prev)
        {
            for (auto& lpSecond : empl_internal(c))
            {
                const bool firstPath = prev[0] == 1;

                if (firstPath)
                {
                    const float probability = lpSecond.second * 0.5;
                    current[lpSecond.first + EdgeFirst] += probability;
                    current[lpSecond.first + EdgeSecond] += probability;
                }
                else
                {
                    const float probability = lpFirst.second * lpSecond.second * 0.5;

                    const int l1 = max(lpFirst.first, lpSecond.first + EdgeFirst);
                    current[l1] += probability;

                    const int l2 = max(lpFirst.first, lpSecond.first + EdgeSecond);
                    current[l2] += probability;
                }
            }
        }

        swap(prev, current);
    }

    return prev;
}

float empl(const Tree& t)
{
    float expected = 0;
    for (const auto& a : empl_internal(t))
    {
        expected += a.first * a.second;
    }

    return expected;
}

测试

int main()
{
    cout << empl(Tree{}) << endl;
    cout << empl(Tree{ {} }) << endl;
    cout << empl(Tree{ {}, {} }) << endl;
    cout << empl(Tree{ { {}, {} }, {} }) << endl;
    cout << empl(Tree{ {}, {}, {} }) << endl;
    cout << empl(Tree{ { {} }, { {} } }) << endl;

    cin.get();
    return 0;
}