<p>You are given an undirected weighted graph of&nbsp;<code>n</code>&nbsp;nodes (0-indexed), represented by an edge list where&nbsp;<code>edges[i] = [a, b]</code>&nbsp;is an undirected edge connecting the nodes&nbsp;<code>a</code>&nbsp;and&nbsp;<code>b</code>&nbsp;with a probability of success of traversing that edge&nbsp;<code>succProb[i]</code>.</p>

<p>Given two nodes&nbsp;<code>start</code>&nbsp;and&nbsp;<code>end</code>, find the path with the maximum probability of success to go from&nbsp;<code>start</code>&nbsp;to&nbsp;<code>end</code>&nbsp;and return its success probability.</p>

<p>If there is no path from&nbsp;<code>start</code>&nbsp;to&nbsp;<code>end</code>, <strong>return&nbsp;0</strong>. Your answer will be accepted if it differs from the correct answer by at most <strong>1e-5</strong>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<p><strong><img alt="" src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex1.png" style="width: 187px; height: 186px;" /></strong></p>

<pre>
<strong>Input:</strong> n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
<strong>Output:</strong> 0.25000
<strong>Explanation:</strong>&nbsp;There are two paths from start to end, one having a probability of success = 0.2 and the other has 0.5 * 0.5 = 0.25.
</pre>

<p><strong class="example">Example 2:</strong></p>

<p><strong><img alt="" src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex2.png" style="width: 189px; height: 186px;" /></strong></p>

<pre>
<strong>Input:</strong> n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
<strong>Output:</strong> 0.30000
</pre>

<p><strong class="example">Example 3:</strong></p>

<p><strong><img alt="" src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex3.png" style="width: 215px; height: 191px;" /></strong></p>

<pre>
<strong>Input:</strong> n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
<strong>Output:</strong> 0.00000
<strong>Explanation:</strong>&nbsp;There is no path between 0 and 2.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>2 &lt;= n &lt;= 10^4</code></li>
	<li><code>0 &lt;= start, end &lt; n</code></li>
	<li><code>start != end</code></li>
	<li><code>0 &lt;= a, b &lt; n</code></li>
	<li><code>a != b</code></li>
	<li><code>0 &lt;= succProb.length == edges.length &lt;= 2*10^4</code></li>
	<li><code>0 &lt;= succProb[i] &lt;= 1</code></li>
	<li>There is at most one edge between every two nodes.</li>
</ul>


class Solution {
public:
    using VertexId = uint16_t;
    using Probability = float;

    static constexpr size_t MaxVertexCount = 10'000;

    double maxProbability(int n, const std::vector<std::vector<int>>& edges, const std::vector<double>& succProb, int start_node, int end_node) {

        for (size_t i = 0; i < edges.size(); ++i)
        {
            const auto& edge = edges[i];
            const auto v1Id = static_cast<VertexId>(edge[0]);
            const auto v2Id = static_cast<VertexId>(edge[1]);
            const auto prob = static_cast<Probability>(succProb[i]);

            auto& v1 = m_vertices[v1Id];
            v1.m_connections.emplace_back(v2Id, prob);

            auto& v2 = m_vertices[v2Id];
            v2.m_connections.emplace_back(v1Id, prob);
        }

        //for (auto& entry : m_vertices)
        //{
        //    auto& connections = entry.m_connections;
        //    std::sort(connections.begin(), connections.end(),
        //        [](const Connection& lhs, const Connection& rhs) {
        //            return lhs.m_prob > rhs.m_prob;
        //        });
        //}

        m_end = static_cast<VertexId>(end_node);
        Visit(m_vertices[start_node], start_node, 1.0f);

        return m_bestProb;
    }

private:
    struct Connection
    {
        VertexId m_id;
        Probability m_prob = 0;
    };

    struct Vertex
    {
        std::vector<Connection> m_connections;
        Probability m_maxProb = 0;
        bool m_visited = false;
    };

    void Visit(Vertex& vertex, const VertexId vertexId, const Probability vertexProb)
    {
        assert(vertex.m_maxProb < vertexProb);
        assert(!vertex.m_visited);

        vertex.m_maxProb = vertexProb;
        if (vertexId == m_end)
        {
            m_bestProb = std::max(m_bestProb, vertexProb);
            return;
        }

        vertex.m_visited = true;

        for (const Connection& c : vertex.m_connections)
        {
            auto& curVertex = m_vertices[c.m_id];
            if (curVertex.m_visited)
                continue;

            const auto newProb = c.m_prob * vertexProb;
            if (newProb < m_bestProb)
                continue;

            if (newProb > curVertex.m_maxProb)
                Visit(curVertex, c.m_id, newProb);
        }

        vertex.m_visited = false;
    }

    std::array<Vertex, MaxVertexCount> m_vertices;
    Probability m_bestProb = 1e-5;
    VertexId m_end;
};
61313