|
| 1 | +# [3373. Maximize the Number of Target Nodes After Connecting Trees II](https://leetcode.com/problems/maximize-the-number-of-target-nodes-after-connecting-trees-ii) |
| 2 | + |
| 3 | +## Description |
| 4 | + |
| 5 | +<div class="elfjS" data-track-load="description_content"><p>There exist two <strong>undirected </strong>trees with <code>n</code> and <code>m</code> nodes, labeled from <code>[0, n - 1]</code> and <code>[0, m - 1]</code>, respectively.</p> |
| 6 | + |
| 7 | +<p>You are given two 2D integer arrays <code>edges1</code> and <code>edges2</code> of lengths <code>n - 1</code> and <code>m - 1</code>, respectively, where <code>edges1[i] = [a<sub>i</sub>, b<sub>i</sub>]</code> indicates that there is an edge between nodes <code>a<sub>i</sub></code> and <code>b<sub>i</sub></code> in the first tree and <code>edges2[i] = [u<sub>i</sub>, v<sub>i</sub>]</code> indicates that there is an edge between nodes <code>u<sub>i</sub></code> and <code>v<sub>i</sub></code> in the second tree.</p> |
| 8 | + |
| 9 | +<p>Node <code>u</code> is <strong>target</strong> to node <code>v</code> if the number of edges on the path from <code>u</code> to <code>v</code> is even. <strong>Note</strong> that a node is <em>always</em> <strong>target</strong> to itself.</p> |
| 10 | + |
| 11 | +<p>Return an array of <code>n</code> integers <code>answer</code>, where <code>answer[i]</code> is the <strong>maximum</strong> possible number of nodes that are <strong>target</strong> to node <code>i</code> of the first tree if you had to connect one node from the first tree to another node in the second tree.</p> |
| 12 | + |
| 13 | +<p><strong>Note</strong> that queries are independent from each other. That is, for every query you will remove the added edge before proceeding to the next query.</p> |
| 14 | + |
| 15 | +<p> </p> |
| 16 | +<p><strong class="example">Example 1:</strong></p> |
| 17 | + |
| 18 | +<div class="example-block"> |
| 19 | +<p><strong>Input:</strong> <span class="example-io">edges1 = [[0,1],[0,2],[2,3],[2,4]], edges2 = [[0,1],[0,2],[0,3],[2,7],[1,4],[4,5],[4,6]]</span></p> |
| 20 | + |
| 21 | +<p><strong>Output:</strong> <span class="example-io">[8,7,7,8,8]</span></p> |
| 22 | + |
| 23 | +<p><strong>Explanation:</strong></p> |
| 24 | + |
| 25 | +<ul> |
| 26 | + <li>For <code>i = 0</code>, connect node 0 from the first tree to node 0 from the second tree.</li> |
| 27 | + <li>For <code>i = 1</code>, connect node 1 from the first tree to node 4 from the second tree.</li> |
| 28 | + <li>For <code>i = 2</code>, connect node 2 from the first tree to node 7 from the second tree.</li> |
| 29 | + <li>For <code>i = 3</code>, connect node 3 from the first tree to node 0 from the second tree.</li> |
| 30 | + <li>For <code>i = 4</code>, connect node 4 from the first tree to node 4 from the second tree.</li> |
| 31 | +</ul> |
| 32 | +<img alt="" src="https://assets.leetcode.com/uploads/2024/09/24/3982-1.png" style="width: 600px; height: 169px;"></div> |
| 33 | + |
| 34 | +<p><strong class="example">Example 2:</strong></p> |
| 35 | + |
| 36 | +<div class="example-block"> |
| 37 | +<p><strong>Input:</strong> <span class="example-io">edges1 = [[0,1],[0,2],[0,3],[0,4]], edges2 = [[0,1],[1,2],[2,3]]</span></p> |
| 38 | + |
| 39 | +<p><strong>Output:</strong> <span class="example-io">[3,6,6,6,6]</span></p> |
| 40 | + |
| 41 | +<p><strong>Explanation:</strong></p> |
| 42 | + |
| 43 | +<p>For every <code>i</code>, connect node <code>i</code> of the first tree with any node of the second tree.</p> |
| 44 | +<img alt="" src="https://assets.leetcode.com/uploads/2024/09/24/3928-2.png" style="height: 281px; width: 500px;"></div> |
| 45 | + |
| 46 | +<p> </p> |
| 47 | +<p><strong>Constraints:</strong></p> |
| 48 | + |
| 49 | +<ul> |
| 50 | + <li><code>2 <= n, m <= 10<sup>5</sup></code></li> |
| 51 | + <li><code>edges1.length == n - 1</code></li> |
| 52 | + <li><code>edges2.length == m - 1</code></li> |
| 53 | + <li><code>edges1[i].length == edges2[i].length == 2</code></li> |
| 54 | + <li><code>edges1[i] = [a<sub>i</sub>, b<sub>i</sub>]</code></li> |
| 55 | + <li><code>0 <= a<sub>i</sub>, b<sub>i</sub> < n</code></li> |
| 56 | + <li><code>edges2[i] = [u<sub>i</sub>, v<sub>i</sub>]</code></li> |
| 57 | + <li><code>0 <= u<sub>i</sub>, v<sub>i</sub> < m</code></li> |
| 58 | + <li>The input is generated such that <code>edges1</code> and <code>edges2</code> represent valid trees.</li> |
| 59 | +</ul> |
| 60 | +</div> |
| 61 | + |
| 62 | +<p> </p> |
| 63 | + |
| 64 | +## Solutions |
| 65 | + |
| 66 | +**Solution: `Depth-First Search`** |
| 67 | + |
| 68 | +- Time complexity: <em>O(m+n)</em> |
| 69 | +- Space complexity: <em>O(m+n)</em> |
| 70 | + |
| 71 | +<p> </p> |
| 72 | + |
| 73 | +### **JavaScript** |
| 74 | + |
| 75 | +```js |
| 76 | +/** |
| 77 | + * @param {number[][]} edges1 |
| 78 | + * @param {number[][]} edges2 |
| 79 | + * @return {number[]} |
| 80 | + */ |
| 81 | +const maxTargetNodes = function (edges1, edges2) { |
| 82 | + const createTree = (edge, n) => { |
| 83 | + const tree = Array.from({ length: n }, () => []); |
| 84 | + |
| 85 | + for (const [a, b] of edge) { |
| 86 | + tree[a].push(b); |
| 87 | + tree[b].push(a); |
| 88 | + } |
| 89 | + |
| 90 | + return tree; |
| 91 | + }; |
| 92 | + |
| 93 | + const m = edges1.length + 1; |
| 94 | + const n = edges2.length + 1; |
| 95 | + const tree1 = createTree(edges1, m); |
| 96 | + const tree2 = createTree(edges2, n); |
| 97 | + |
| 98 | + const getNodeCount = (tree, isEven) => { |
| 99 | + const count = Array.from({ length: 2 }, () => 0); |
| 100 | + |
| 101 | + const dfsTree = (node, prev, index) => { |
| 102 | + count[index] += 1; |
| 103 | + |
| 104 | + for (const neighbor of tree[node]) { |
| 105 | + if (prev === neighbor) continue; |
| 106 | + |
| 107 | + dfsTree(neighbor, node, index ^ 1); |
| 108 | + } |
| 109 | + }; |
| 110 | + |
| 111 | + dfsTree(0, -1, isEven ? 1 : 0); |
| 112 | + |
| 113 | + return count; |
| 114 | + }; |
| 115 | + |
| 116 | + const count1 = getNodeCount(tree1, true); |
| 117 | + const count2 = getNodeCount(tree2, false); |
| 118 | + const maxPathCount = Math.max(...count2); |
| 119 | + const path = Array.from({ length: m }, () => false); |
| 120 | + |
| 121 | + const setNodePath = (node, prev, isEven) => { |
| 122 | + path[node] = isEven; |
| 123 | + |
| 124 | + for (const neighbor of tree1[node]) { |
| 125 | + if (prev === neighbor) continue; |
| 126 | + |
| 127 | + setNodePath(neighbor, node, !isEven); |
| 128 | + } |
| 129 | + }; |
| 130 | + |
| 131 | + setNodePath(0, -1, true); |
| 132 | + |
| 133 | + return path.map(isEven => maxPathCount + count1[isEven ? 1 : 0]); |
| 134 | +}; |
| 135 | +``` |
0 commit comments