Skip to content

USACO 2022 US Open Contest Silver Division - Visits#

Problem link: here

Solution Author: Stefan Dascalescu

Problem Solution#

Create a directed graph, and each node only has one edge going out. Whever there is a cycle, you can include all but one edge, so whenever you see a cycle, find the smallest value of all the edges in the cycle and remove that from the total sum of edges.

Source code#

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

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

int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    vector<int> v(n);

    vector<pair<int, int>> g(n);

    long long total_weight = 0;

    for (int i = 0; i < n; i++) {
        cin >> a[i] >> v[i];
        a[i]--;
        g[i] = {a[i], v[i]};
        total_weight += v[i];
    }

    vector<bool> visited(n);
    long long total_weight_removed = 0;

    for (int i = 0; i < n; i++) {
        if (!visited[i]) {
            vector<int> nodes;
            nodes.push_back(i);
            visited[i] = true;
            int buddy = g[i].first;

            while (!visited[buddy]) {
                nodes.push_back(buddy);
                visited[buddy] = true;
                buddy = g[buddy].first;
            }

            bool cycle = false;
            int smallest = 1e9;
            for (int i = 0; i < nodes.size(); i++) {
                if (nodes[i] == buddy) {
                    cycle = true;
                }
                if (cycle) {
                    smallest = min(smallest, g[nodes[i]].second);
                }
            }
            if (cycle) total_weight_removed += smallest;
        }
    }
    cout << total_weight - total_weight_removed << '\n';
}