Template

template.cpp

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

#define STR_(x) #x
#define STR(x) STR_(x)

using ll = long long;
const ll INF = LLONG_MAX - 10;

ll max(int x, ll y) { return std::max((ll) x, y); }
ll max(ll y, int x) { return std::max((ll) x, y); }
ll min(int x, ll y) { return std::min((ll) x, y); }
ll min(ll y, int x) { return std::min((ll) x, y); }

struct Coordinate
{
    ll x, y;
 
    static void sortByX(vector<Coordinate*>& vec)
    {
        sort(vec.begin(), vec.end(), [](Coordinate* a, Coordinate* b) {
            return a->x < b->x;
        });
    }
 
    static void sortByY(vector<Coordinate*>& vec)
    {
        sort(vec.begin(), vec.end(), [](Coordinate* a, Coordinate* b) {
            return a->y < b->y;
        });
    }
};
 
struct Rect
{
    ll x1, y1, x2, y2;
 
    friend ostream& operator<<(ostream& os, const Rect& rect)
    {
        return os << rect.x1 << ' ' << rect.y1 << ' ' << rect.x2 << ' ' << rect.y2;
    }
 
    friend istream& operator>>(istream& is, Rect& rect)
    {
        return is >> rect.x1 >> rect.y1 >> rect.x2 >> rect.y2;
    }
};
 
template<typename Grid>
void cartesianPrint(const Grid& grid, int rows, int cols)
{
    if (rows < 0 || cols < 0)
    {
        throw invalid_argument("rows and cols must be non-negative");
    }

    vector<int> colWidths(cols);

    for (int c = 0; c < cols; ++c)
    {
        colWidths[c] = static_cast<int>(to_string(c).size());

        for (int r = 0; r < rows; ++r)
        {
            ll value = grid[r][c];
            int width = static_cast<int>(to_string(value).size());
            colWidths[c] = max(colWidths[c], width);
        }
    }

    int rowLabelWidth = max(3, static_cast<int>(to_string(rows - 1).size()));

    // ---- Column labels (TOP) ----
    cerr << string(rowLabelWidth, ' ') << "   ";

    for (int c = 0; c < cols; ++c)
    {
        cerr << setw(colWidths[c]) << c;

        if (c < cols - 1)
        {
            cerr << ' ';
        }
    }

    cerr << '\n';

    cerr << string(rowLabelWidth, ' ') << " +";

    for (int c = 0; c < cols; ++c)
    {
        cerr << string(colWidths[c] + 1, '-');
    }

    cerr << '\n';

    // ---- Rows ----
    for (int r = 0; r < rows; ++r)
    {
        cerr << setw(rowLabelWidth) << r << " | ";

        for (int c = 0; c < cols; ++c)
        {
            cerr << setw(colWidths[c]) << grid[r][c];

            if (c < cols - 1)
            {
                cerr << ' ';
            }
        }

        cerr << '\n';
    }
}
 
const vector<pair<int, int>> dirs = {
    {1, 0}, {0, 1}, {-1, 0}, {0, -1},
    {1, 1}, {-1, 1}, {-1, -1}, {1, -1}
};
const vector<pair<int, int>> dirs4 = {
    {1, 0}, {0, 1}, {-1, 0}, {0, -1}
};
const int MOD = 1000000007;
constexpr double epsilon = 0.00001;

struct MCMF {
    struct edge {
        int from, to, rev;
        ll cap, cost, flow;
    };
    int N;
    vector<vector<edge>> ed;
    vector<int> seen;
    vector<ll> dist, pi;
    vector<edge*> par;

    MCMF(int N_in) : N(N_in), ed(N_in), seen(N_in), dist(N_in), pi(N_in), par(N_in) {}

    void addEdge(int from, int to, ll cap, ll cost) {
        if (from == to) return;
        ed[from].push_back(edge{ from,to,(int)ed[to].size(),cap,cost,0 });
        ed[to].push_back(edge{ to,from,(int)ed[from].size()-1,0,-cost,0 });
    }

    void path(int s) {
        fill(seen.begin(), seen.end(), 0);
        fill(dist.begin(), dist.end(), INF);
        dist[s] = 0; ll di;

        priority_queue<pair<ll, int>> q;
        q.push({ 0, s });

        while (!q.empty()) {
            s = q.top().second; q.pop();
            if (seen[s]) continue; // outdated entry
            seen[s] = 1; di = dist[s] + pi[s];
            for (edge& e : ed[s]) if (!seen[e.to]) {
                ll val = di - pi[e.to] + e.cost;
                if (e.cap - e.flow > 0 && val < dist[e.to]) {
                    dist[e.to] = val;
                    par[e.to] = &e;
                    q.push({ -dist[e.to], e.to });
                }
            }
        }
        for (int i = 0; i < N; i++) pi[i] = min(pi[i] + dist[i], INF);
    }

    pair<ll, ll> maxflow(int s, int t) {
        ll totflow = 0, totcost = 0;
        while (path(s), seen[t]) {
            ll fl = INF;
            for (edge* x = par[t]; x; x = par[x->from])
                fl = min(fl, x->cap - x->flow);

            totflow += fl;
            for (edge* x = par[t]; x; x = par[x->from]) {
                x->flow += fl;
                ed[x->to][x->rev].flow -= fl;
            }
        }
        for (int i = 0; i < N; i++) for(edge& e : ed[i]) totcost += e.cost * e.flow;
        return {totflow, totcost/2};
    }

    // If some costs can be negative, call this before maxflow:
    void setpi(int s) { // (otherwise, leave this out)
        fill(pi.begin(), pi.end(), INF); pi[s] = 0;
        int it = N, ch = 1; ll v;
        while (ch-- && it--)
            for (int i = 0; i < N; i++) if (pi[i] != INF)
                for (edge& e : ed[i]) if (e.cap)
                    if ((v = pi[i] + e.cost) < pi[e.to])
                        pi[e.to] = v, ch = 1;
        assert(it >= 0); // negative cost cycle
    }
};

class UnionFind
{
private:
    std::vector<int> root;

public:
    UnionFind(size_t size)
    {
        root.resize(size);
        for (size_t i = 0; i < size; i++)
        {
            root[i] = i;
        }
    }

    int find(int x)
    {
        return root[x];
    }

    void unionSets(int x, int y)
    {
        int rootX = find(x);
        int rootY = find(y);

        if (rootX != rootY)
        {
            for (size_t i = 0; i < root.size(); i++)
            {
                if (root[i] == rootY)
                {
                    root[i] = rootX;
                }
            }
        }
    }

    bool connected(int x, int y)
    {
        return find(x) == find(y);
    }

    int numSets()
    {
        unordered_set<int> uniqueRoots;
        for (size_t i = 0; i < root.size(); i++)
        {
            uniqueRoots.insert(find(i));
        }
        return static_cast<int>(uniqueRoots.size());
    }
};

class Graph
{
public:

    struct Edge
    {
        int from;
        int end;
        ll weight;

        Edge(int e, ll w)
            : from(-1), end(e), weight(w)
        { }

        Edge(int f, int e, ll w)
            : from(f), end(e), weight(w)
        { }
    };

private:

    vector<size_t> head;
    vector<int> to;
    vector<ll> weight;
    vector<size_t> next;

    size_t n;
    size_t idx = 1;

    bool directed;

    void check(int v) const
    {
        if (v < 0 || static_cast<size_t>(v) >= n)
        {
            throw out_of_range("vertex out of range");
        }
    }

    void addOne(int s, int e, ll w)
    {
        if (idx >= to.size())
        {
            throw overflow_error("edge capacity exceeded");
        }

        to[idx] = e;
        weight[idx] = w;
        next[idx] = head[s];
        head[s] = idx++;
    }

public:

    Graph(size_t size, bool isDirected = true)
        : Graph(size, size * (size - 1), isDirected)
    { }

    Graph(size_t size, size_t edgeCapacity, bool isDirected = true)
        : head(size, 0),
          to(edgeCapacity + 1),
          weight(edgeCapacity + 1),
          next(edgeCapacity + 1),
          n(size),
          directed(isDirected)
    {
    }

    void add(int start, int end, ll w)
    {
        check(start);
        check(end);

        addOne(start, end, w);

        if (!directed)
        {
            addOne(end, start, w);
        }
    }

    bool isConnected(int start, int end) const
    {
        check(start);
        check(end);

        for (size_t i = head[start]; i; i = next[i])
        {
            if (to[i] == end)
            {
                return true;
            }
        }

        return false;
    }

    vector<Edge> outEdges(int start) const
    {
        check(start);

        vector<Edge> res;

        for (size_t i = head[start]; i; i = next[i])
        {
            res.emplace_back(to[i], weight[i]);
        }

        return res;
    }

    size_t size() const
    {
        return n;
    }

    bool isDirected() const
    {
        return directed;
    }
};


int main()
{
    void solve();

    #if defined(USACO) && !defined(LOCAL)
        freopen(STR(USACO) ".in", "r", stdin);
        freopen(STR(USACO) ".out", "w", stdout);
    #endif

    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    solve();

    return 0;
}
/*------------------------------------------------------------------------*/



void solve()
{
    
}

Makefile

CXX      = g++
CXXFLAGS = -O2 -DLOCAL

release: main

main: main.cpp
	$(CXX) $(CXXFLAGS) main.cpp -o main

# Run every X.in that has a matching X.out, then print X-pass / X-fail.
run: main
	@tmp=$$(mktemp); found=0; \
	for in in $$(ls *.in 2>/dev/null | sort -V); do \
		t=$${in%.in}; [ -f "$$t.out" ] || continue; found=1; \
		if (./main < "$$in" > "$$tmp"; exit $$?) 2>/dev/null && diff -bBq "$$tmp" "$$t.out" >/dev/null; \
		then printf '\033[32m%s-pass\033[0m\n' "$$t"; \
		else printf '\033[31m%s-fail\033[0m\n' "$$t"; fi; \
	done; \
	rm -f "$$tmp"; \
	[ $$found = 1 ] || echo "no .in/.out pairs found"

.PHONY: release run