Skip to content

USACO 2020 January Contest Silver Division - Wormhole Sort#

Problem link: here

Solution Author: Stefan Dascalescu

Problem Solution#

Binary search for the min width. For each step of the binary search, we apply DFS to check whether that minimal width is achievable.

Source code#

The source code in C++ can be seen below.

#include <bits/stdc++.h>
using namespace std;

int n, m;
vector<bool> visited(1e5 + 1);
vector<int> locs(1e5 + 1);
vector<int> indices(1e5 + 1);
vector<vector<pair<int, int>>> adj(1e5 + 1, vector<pair<int, int>>(0));

void dfs(int start, int min_width) {
    visited[start] = true;
    for (pair<int, int> a : adj[start]) {
        if (a.second >= min_width && !visited[a.first]) {
            dfs(a.first, min_width);
        }
    }
}

bool ok(int min_width) {
    fill(visited.begin(), visited.end(), false);
    dfs(1, min_width);
    for (int i = 1; i <= n; i++) {
        if (!visited[i] && locs[i] != i) {
            return false;
        }
    }
    return true;
}

int main() {
    freopen("wormsort.in", "r", stdin);
    freopen("wormsort.out", "w", stdout);

    cin >> n >> m;
    bool flag = true;
    for (int i = 1; i <= n; i++) {
        cin >> locs[i];
        if (locs[i] != i) {
            flag = false;
        }
        indices[locs[i]] = i;
    }
    if (flag) {
        cout << -1 << endl;
        return 0;
    }

    int r = 0;
    for (int i = 0; i < m; i++) {
        int a, b, w;
        cin >> a >> b >> w;
        adj[indices[b]].push_back({indices[a], w});
        adj[indices[a]].push_back({indices[b], w});
        r = max(r, w);
    }

    int l = 0;
    while (l <= r) {
        int mid = l + (r - l) / 2;
        if (ok(mid)) {
            l = mid + 1;
        } 
        else {
            r = mid - 1;
        }
    }
    cout << l - 1 << "\n";
    return 0;
}