<p>You are given two integer arrays <code>nums1</code> and <code>nums2</code> of length <code>n</code>.</p>

<p>The <strong>XOR sum</strong> of the two integer arrays is <code>(nums1[0] XOR nums2[0]) + (nums1[1] XOR nums2[1]) + ... + (nums1[n - 1] XOR nums2[n - 1])</code> (<strong>0-indexed</strong>).</p>

<ul>
	<li>For example, the <strong>XOR sum</strong> of <code>[1,2,3]</code> and <code>[3,2,1]</code> is equal to <code>(1 XOR 3) + (2 XOR 2) + (3 XOR 1) = 2 + 0 + 2 = 4</code>.</li>
</ul>

<p>Rearrange the elements of <code>nums2</code> such that the resulting <strong>XOR sum</strong> is <b>minimized</b>.</p>

<p>Return <em>the <strong>XOR sum</strong> after the rearrangement</em>.</p>

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

<pre>
<strong>Input:</strong> nums1 = [1,2], nums2 = [2,3]
<strong>Output:</strong> 2
<b>Explanation:</b> Rearrange <code>nums2</code> so that it becomes <code>[3,2]</code>.
The XOR sum is (1 XOR 3) + (2 XOR 2) = 2 + 0 = 2.</pre>

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

<pre>
<strong>Input:</strong> nums1 = [1,0,3], nums2 = [5,3,4]
<strong>Output:</strong> 8
<b>Explanation:</b> Rearrange <code>nums2</code> so that it becomes <code>[5,4,3]</code>. 
The XOR sum is (1 XOR 5) + (0 XOR 4) + (3 XOR 3) = 4 + 4 + 0 = 8.
</pre>

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

<ul>
	<li><code>n == nums1.length</code></li>
	<li><code>n == nums2.length</code></li>
	<li><code>1 &lt;= n &lt;= 14</code></li>
	<li><code>0 &lt;= nums1[i], nums2[i] &lt;= 10<sup>7</sup></code></li>
</ul>

INF = 10**10

class Edge:
    def __init__(self, from_vertex: int, to_vertex: int, capacity: int, cost: int, flow: int) -> None:
        self.from_vertex = from_vertex
        self.to_vertex = to_vertex
        self.capacity = capacity
        self.cost = cost
        self.flow = flow

class MinCostMaxFlow:
    def __init__(self, total_vertices: int, source: int, sink: int):
        self.total_vertices = total_vertices
        self.source = source
        self.sink = sink
        self.edges = []
        self.graph = [[] for _ in range(total_vertices)]
        self.distances = [INF] * total_vertices
        self.flow_values = [0] * total_vertices
        self.previous = [-1] * total_vertices

    def add_edge(self, from_vertex: int, to_vertex: int, capacity: int, cost: int) -> None:
        self.edges.append(Edge(from_vertex, to_vertex, capacity, cost, 0))
        self.edges.append(Edge(to_vertex, from_vertex, 0, -cost, 0))
        self.graph[from_vertex].append(len(self.edges) - 2)
        self.graph[to_vertex].append(len(self.edges) - 1)

    def find_augmenting_path(self) -> bool:
        self.flow_values = [0] * self.total_vertices
        self.previous = [-1] * self.total_vertices
        self.distances = [INF] * self.total_vertices
        self.distances[self.source] = 0
        self.flow_values[self.source] = INF

        priority_queue = [(0, self.source)]

        while priority_queue:
            dist_u, u = heappop(priority_queue)
            if dist_u > self.distances[u]:
                continue
            for edge_index in self.graph[u]:
                edge = self.edges[edge_index]
                v = edge.to_vertex
                if edge.capacity - edge.flow > 0:
                    new_distance = self.distances[u] + edge.cost
                    if new_distance < self.distances[v]:
                        self.distances[v] = new_distance
                        self.previous[v] = edge_index
                        self.flow_values[v] = min(self.flow_values[u], edge.capacity - edge.flow)
                        heappush(priority_queue, (self.distances[v], v))

        return self.previous[self.sink] != -1

    def compute(self) -> Tuple[int, int]:
        max_flow, min_cost = 0, 0
        while self.find_augmenting_path():
            flow = self.flow_values[self.sink]
            max_flow += flow
            min_cost += flow * self.distances[self.sink]
            current_vertex = self.sink
            while current_vertex != self.source:
                edge_index = self.previous[current_vertex]
                self.edges[edge_index].flow += flow
                self.edges[edge_index ^ 1].flow -= flow
                current_vertex = self.edges[edge_index].from_vertex
        return max_flow, min_cost

class Solution:
    def minimumXORSum(self, nums1: List[int], nums2: List[int]) -> int:
        n = len(nums1)
        source = 2 * n
        sink = source + 1
        network = MinCostMaxFlow(2 * n + 2, source, sink)
        
        for i in range(n):
            network.add_edge(source, i, 1, 0)
        
        for i in range(n):
            for j in range(n):
                cost = nums1[i] ^ nums2[j]
                network.add_edge(i, j + n, 1, cost)
        
        for i in range(n):
            network.add_edge(i + n, sink, 1, 0)
        
        _, min_cost = network.compute()
        return min_cost
73