1. Abridged Problem Statement  
Given an n×n matrix of unsafety values a[i][j], assign exactly one program to each of the n computers (i.e. find a perfect matching) so as to minimize the maximum unsafety value among the chosen assignments. Output that minimal maximum value and one corresponding assignment of programs to computers.

2. Detailed Editorial  

Problem restatement  
• We have n computers and n programs. Each cell a[i][j] is the unsafety of running program j on computer i.  
• We seek a permutation p of {1…n} so that max_{1≤i≤n} a[i][p(i)] is as small as possible.  

Observations  
• This is the classic “bottleneck assignment” problem.  
• Equivalently, we ask: what is the smallest threshold T such that we can pick one edge in each row and each column with weight ≤ T?  

Solution approach  
1. Flatten and sort all n² entries by weight, yielding an array edges of (weight, row, col).  
2. Binary search on the index mid in this sorted array: define threshold = edges[mid].weight.  
3. Build a bipartite graph G(mid) with left side = computers (0…n−1), right side = programs (0…n−1), and include an edge (i→j) whenever a[i][j] ≤ threshold.  
4. Use Hopcroft–Karp to check if G(mid) has a perfect matching of size n.  
   – If yes, we can lower the threshold (move high = mid−1).  
   – Otherwise, raise the threshold (move low = mid+1).  
5. After binary search, low points to the smallest mid where perfect matching exists. Rebuild the graph at that mid, compute one maximum matching, and output the threshold and the matching.  

Complexity  
• Sorting: O(n² log n²) = O(n² log n).  
• Each bipartite matching test: Hopcroft–Karp runs in O(E √V) = O((n²) √n).  
• We perform O(log(n²)) = O(log n) matching tests.  
• Total ≃ O(n² log n + n² √n log n), safe for n up to 500.  

3. C++ Solution

```cpp
#include <bits/stdc++.h>
// #include <coding_library/graph/maxflow.hpp>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

class HopcroftKarp {
  private:
    int n, m;
    vector<int> dist;

    bool bfs() {
        queue<int> q;
        dist.assign(n, -1);
        for(int u = 0; u < n; ++u) {
            if(inv_match[u] == -1) {
                dist[u] = 0;
                q.push(u);
            }
        }

        bool found = false;
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            for(int v: adj[u]) {
                int m = match[v];
                if(m == -1) {
                    found = true;
                } else if(dist[m] == -1) {
                    dist[m] = dist[u] + 1;
                    q.push(m);
                }
            }
        }

        return found;
    }

    bool dfs(int u) {
        for(int v: adj[u]) {
            int m = match[v];
            if(m == -1 || (dist[m] == dist[u] + 1 && dfs(m))) {
                inv_match[u] = v;
                match[v] = u;
                return true;
            }
        }
        dist[u] = -1;
        return false;
    }

  public:
    vector<int> match, inv_match;
    vector<vector<int>> adj;

    HopcroftKarp(int _n, int _m = -1) : n(_n), m(_m == -1 ? _n : _m) {
        adj.assign(n, vector<int>());
        clear(false);
    }

    void clear(bool clear_adj = true) {
        match.assign(m, -1);
        inv_match.assign(n, -1);
        if(clear_adj) {
            adj.assign(n, vector<int>());
        }
    }

    void add_edge(int u, int v) { adj[u].push_back(v); }

    int max_matching(bool shuffle_edges = false) {
        if(shuffle_edges) {
            for(int i = 0; i < n; i++) {
                shuffle(
                    adj[i].begin(), adj[i].end(),
                    mt19937(
                        chrono::steady_clock::now().time_since_epoch().count()
                    )
                );
            }
        }

        int ans = 0;
        while(bfs()) {
            for(int u = 0; u < n; ++u) {
                if(inv_match[u] == -1 && dfs(u)) {
                    ans++;
                }
            }
        }
        return ans;
    }

    vector<pair<int, int>> get_matching() {
        vector<pair<int, int>> matches;
        for(int u = 0; u < n; ++u) {
            if(inv_match[u] != -1) {
                matches.emplace_back(u, inv_match[u]);
            }
        }
        return matches;
    }

    pair<vector<int>, vector<int>> minimum_vertex_cover() {
        vector<int> left_cover, right_cover;
        bfs();

        for(int u = 0; u < n; ++u) {
            if(dist[u] == -1) {
                left_cover.push_back(u);
            }
        }

        for(int v = 0; v < m; ++v) {
            if(match[v] != -1 && dist[match[v]] != -1) {
                right_cover.push_back(v);
            }
        }

        return {left_cover, right_cover};
    }
};

using BipartiteMatching = HopcroftKarp;

int n;
vector<vector<int>> a;

void read() {
    cin >> n;
    a.assign(n, vector<int>(n));
    cin >> a;
}

BipartiteMatching eval(int mid, const vector<array<int, 3>>& edges) {
    vector<array<int, 3>> edges2;
    for(auto [w, u, v]: edges) {
        if(w <= edges[mid][0]) {
            edges2.push_back({w, u, v});
        }
    }

    int m = edges2.size();
    BipartiteMatching bm(n);
    for(auto [w, u, v]: edges2) {
        bm.add_edge(u, v);
    }

    return bm;
}

void solve() {
    // We want to assign programs to workstations (a perfect matching of an
    // n x n bipartite graph) minimizing the maximum used unsafety value. Sort
    // all n^2 (value, computer, program) entries and binary search on the
    // threshold index mid: keeping only edges with value <= edges[mid][0], a
    // perfect matching of size n exists iff the threshold is feasible. Feasible
    // thresholds are monotone, so we binary search for the smallest one using
    // Hopcroft-Karp to test for a perfect matching, then rebuild the matching at
    // the answer threshold and print the pairing.

    vector<array<int, 3>> edges;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            edges.push_back({a[i][j], i, j});
        }
    }

    sort(edges.begin(), edges.end());

    int low = 0, high = n * n - 1, ans = -1;
    while(low <= high) {
        int mid = (low + high) / 2;
        if(eval(mid, edges).max_matching(true) == n) {
            ans = mid;
            high = mid - 1;
        } else {
            low = mid + 1;
        }
    }

    BipartiteMatching bm = eval(ans, edges);
    bm.max_matching();
    cout << edges[ans][0] << '\n';
    auto matching = bm.get_matching();
    for(auto [u, v]: matching) {
        cout << u + 1 << ' ' << v + 1 << '\n';
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

4. Python Solution with Detailed Comments  

```python
import sys
import threading
def main():
    import sys
    sys.setrecursionlimit(10000)
    input = sys.stdin.readline

    n = int(input())
    a = [list(map(int, input().split())) for _ in range(n)]

    # Build a list of all edges: (weight, row, col)
    edges = []
    for i in range(n):
        for j in range(n):
            edges.append((a[i][j], i, j))
    edges.sort(key=lambda x: x[0])

    # Hopcroft-Karp implementation
    from collections import deque
    INF = 10**9

    def hopcroft_karp(adj, N, M):
        pairU = [-1]*N   # pairU[u] = matched v for u, or -1
        pairV = [-1]*M   # pairV[v] = matched u for v, or -1
        dist = [0]*N

        def bfs():
            queue = deque()
            for u in range(N):
                if pairU[u] < 0:
                    dist[u] = 0
                    queue.append(u)
                else:
                    dist[u] = INF
            found = False
            while queue:
                u = queue.popleft()
                for v in adj[u]:
                    pu = pairV[v]
                    if pu < 0:
                        found = True
                    elif dist[pu] == INF:
                        dist[pu] = dist[u] + 1
                        queue.append(pu)
            return found

        def dfs(u):
            for v in adj[u]:
                pu = pairV[v]
                if pu < 0 or (dist[pu] == dist[u] + 1 and dfs(pu)):
                    pairU[u] = v
                    pairV[v] = u
                    return True
            dist[u] = INF
            return False

        matching = 0
        while bfs():
            for u in range(N):
                if pairU[u] < 0 and dfs(u):
                    matching += 1
        return matching, pairU

    # Build adjacency up to index mid
    def build_adj(mid):
        adj = [[] for _ in range(n)]
        for i in range(mid+1):
            _, u, v = edges[i]
            adj[u].append(v)
        return adj

    # Binary search for minimal mid that allows perfect matching
    low, high, ans = 0, n*n-1, n*n-1
    while low <= high:
        mid = (low + high)//2
        adj = build_adj(mid)
        match_sz, _ = hopcroft_karp(adj, n, n)
        if match_sz == n:
            ans = mid
            high = mid - 1
        else:
            low = mid + 1

    # Rebuild final matching
    adj = build_adj(ans)
    _, pairU = hopcroft_karp(adj, n, n)

    # Output result
    threshold = edges[ans][0]
    out = [str(threshold)]
    for i in range(n):
        # pairU[i] is the column matched to row i
        out.append(f"{i+1} {pairU[i]+1}")
    sys.stdout.write("\n".join(out))

if __name__ == "__main__":
    main()
```

Comments in the code explain each part: reading input, sorting edges, binary search on threshold, Hopcroft–Karp algorithm (BFS for layers, DFS for augmenting), rebuilding final matching, and printing.

5. Compressed Editorial  
• This is the bottleneck assignment: minimize the max edge in a perfect matching of an n×n weight matrix.  
• Sort all edges and binary search on the largest allowed weight.  
• For each threshold, build a bipartite graph including edges up to that weight and check for a perfect matching via Hopcroft–Karp in O(E√V).  
• Total complexity O(n² log n + n²√n log n), fine for n=500.