<p>There is a network of <code>n</code> servers, labeled from <code>0</code> to <code>n - 1</code>. You are given a 2D integer array <code>edges</code>, where <code>edges[i] = [u<sub>i</sub>, v<sub>i</sub>]</code> indicates there is a message channel between servers <code>u<sub>i</sub></code> and <code>v<sub>i</sub></code>, and they can pass <strong>any</strong> number of messages to <strong>each other</strong> directly in <strong>one</strong> second. You are also given a <strong>0-indexed</strong> integer array <code>patience</code> of length <code>n</code>.</p>

<p>All servers are <strong>connected</strong>, i.e., a message can be passed from one server to any other server(s) directly or indirectly through the message channels.</p>

<p>The server labeled <code>0</code> is the <strong>master</strong> server. The rest are <strong>data</strong> servers. Each data server needs to send its message to the master server for processing and wait for a reply. Messages move between servers <strong>optimally</strong>, so every message takes the <strong>least amount of time</strong> to arrive at the master server. The master server will process all newly arrived messages <strong>instantly</strong> and send a reply to the originating server via the <strong>reversed path</strong> the message had gone through.</p>

<p>At the beginning of second <code>0</code>, each data server sends its message to be processed. Starting from second <code>1</code>, at the <strong>beginning</strong> of <strong>every</strong> second, each data server will check if it has received a reply to the message it sent (including any newly arrived replies) from the master server:</p>

<ul>
	<li>If it has not, it will <strong>resend</strong> the message periodically. The data server <code>i</code> will resend the message every <code>patience[i]</code> second(s), i.e., the data server <code>i</code> will resend the message if <code>patience[i]</code> second(s) have <strong>elapsed</strong> since the <strong>last</strong> time the message was sent from this server.</li>
	<li>Otherwise, <strong>no more resending</strong> will occur from this server.</li>
</ul>

<p>The network becomes <strong>idle</strong> when there are <strong>no</strong> messages passing between servers or arriving at servers.</p>

<p>Return <em>the <strong>earliest second</strong> starting from which the network becomes <strong>idle</strong></em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="example 1" src="https://assets.leetcode.com/uploads/2021/09/22/quiet-place-example1.png" style="width: 750px; height: 384px;" />
<pre>
<strong>Input:</strong> edges = [[0,1],[1,2]], patience = [0,2,1]
<strong>Output:</strong> 8
<strong>Explanation:</strong>
At (the beginning of) second 0,
- Data server 1 sends its message (denoted 1A) to the master server.
- Data server 2 sends its message (denoted 2A) to the master server.

At second 1,
- Message 1A arrives at the master server. Master server processes message 1A instantly and sends a reply 1A back.
- Server 1 has not received any reply. 1 second (1 &lt; patience[1] = 2) elapsed since this server has sent the message, therefore it does not resend the message.
- Server 2 has not received any reply. 1 second (1 == patience[2] = 1) elapsed since this server has sent the message, therefore it resends the message (denoted 2B).

At second 2,
- The reply 1A arrives at server 1. No more resending will occur from server 1.
- Message 2A arrives at the master server. Master server processes message 2A instantly and sends a reply 2A back.
- Server 2 resends the message (denoted 2C).
...
At second 4,
- The reply 2A arrives at server 2. No more resending will occur from server 2.
...
At second 7, reply 2D arrives at server 2.

Starting from the beginning of the second 8, there are no messages passing between servers or arriving at servers.
This is the time when the network becomes idle.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="example 2" src="https://assets.leetcode.com/uploads/2021/09/04/network_a_quiet_place_2.png" style="width: 100px; height: 85px;" />
<pre>
<strong>Input:</strong> edges = [[0,1],[0,2],[1,2]], patience = [0,10,10]
<strong>Output:</strong> 3
<strong>Explanation:</strong> Data servers 1 and 2 receive a reply back at the beginning of second 2.
From the beginning of the second 3, the network becomes idle.
</pre>

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

<ul>
	<li><code>n == patience.length</code></li>
	<li><code>2 &lt;= n &lt;= 10<sup>5</sup></code></li>
	<li><code>patience[0] == 0</code></li>
	<li><code>1 &lt;= patience[i] &lt;= 10<sup>5</sup></code> for <code>1 &lt;= i &lt; n</code></li>
	<li><code>1 &lt;= edges.length &lt;= min(10<sup>5</sup>, n * (n - 1) / 2)</code></li>
	<li><code>edges[i].length == 2</code></li>
	<li><code>0 &lt;= u<sub>i</sub>, v<sub>i</sub> &lt; n</code></li>
	<li><code>u<sub>i</sub> != v<sub>i</sub></code></li>
	<li>There are no duplicate edges.</li>
	<li>Each server can directly or indirectly reach another server.</li>
</ul>

class Solution:
    def networkBecomesIdle(self, edges: List[List[int]], patience: List[int]) -> int:
        # each server can send any number of messages to another, so no bottle neck (each computer's
        # message takes the same amount of time to make it to master server, no matter what the
        # state of the server is). This means computers can be considered individually. In Example 1, 
        # the path length for server 1 to 0 is 1, so the reply takes 2 edges (2) seconds to get back.
        # In other words, from second 2 computer 1 has stopped. The last time computer 1 sent a message
        # was at second 0, it took 2 seconds to return so computer 1's work can be thought to end at
        # second 3 (ie, if Example 1 was edited to remove server 2, the output of only server 1's work
        # would be 3). Server 2 in Example 1 stops sending at second 4. The last time server 2 would
        # send a message is at second 3. This takes 4 seconds to get back (twice the path length),
        # server 2's work is done by second 7, so it is idle from second 8. Out of all these non
        # master servers, server 2 takes the longest (8 > 4) so the answer is 4.

        # Process: each computer wants to know when they will stop sending message, this is equal to
        # when they receive their reply, which is 2 times their shortest path to 0. To calculate 
        # everybody's shortest path to 0, we can do the reverse: run a shortest path algorithm from 
        # server 0. Since each edge is weight equally (1), any path finding algorithm works, will use
        # bfs.

        # Now that a server can calculate when they will stop sending messages, when will they have 
        # sent their last message? They send a message every patience[i] seconds, this means they send
        # a message every patience[i] seconds. If their reply arrives at second m, the last second
        # they could send a message is m-1. The formula for the last second a message was sent is
        # ((m-1) // patience[i] )* patience[i]. This calculates the number of FULL multiples of 
        # patience[i] in m-1, then finds what that number is. ex: if m-1 = 5 and patience[i] = 2,
        # this says the last message was sent at second 4. Alternate formula is 
        # (m-1) - [(m-1) % patience[i]].

        # With this, we can see when a computer's last second of work is done (this idea considers
        # each computer's reply being part of their work).

        distance_from_master = dict()

        graph = defaultdict(set)
        for nodeA, nodeB in edges:
            nodeA_edges = graph[nodeA]
            nodeA_edges.add(nodeB)
            graph[nodeA] = nodeA_edges

            nodeB_edges = graph[nodeB]
            nodeB_edges.add(nodeA)
            graph[nodeB] = nodeB_edges

        level = set()
        level.add(0)
        distance = 0
        seen = set()

        while len(level) > 0:
            next_level = set()

            for curr in level:
                if curr in seen:
                    continue
                seen.add(curr)
                distance_from_master[curr] = distance

                for neighbor in graph[curr]:
                    if neighbor in seen:
                        continue

                    next_level.add(neighbor)

            level = next_level
            distance += 1

        max_time = 0
        for server in range(len(patience)):
            if server == 0:
                continue

            reply_time = distance_from_master[server] * 2
            last_message_time = ( (reply_time-1) // patience[server] ) * patience[server]
            max_time = max(max_time, last_message_time + reply_time + 1)

        return max_time
            
1825