Language: C++

#include <iostream>
#include <vector>
#include <cassert>
#include <queue>
#include <fstream>
#include <set>

#define VARNAME(x) #x
#define show(x) cerr << #x << " = " << x << endl

using namespace std;
using ll = long long;
template <typename T>
constexpr T INF = numeric_limits<T>::max() / 10;

class CostFlow
{
public:
    using Cost = int;
    using Ind = int;
    using Capacity = int;
    using T = int;

    struct Edge {
        Edge(const Ind from_, const Ind to_, const Ind reverse_, const Capacity capacity_, const Cost cost_, bool is_reverse_ = false) : from{from_}, to{to_}, reverse{reverse_}, capacity{capacity_}, flow{0}, cost{cost_}, is_reverse{is_reverse_} {}
        Ind from;
        Ind to;
        Ind reverse;
        Capacity capacity;
        Capacity flow;
        Cost cost;
        bool is_reverse;
    };

    CostFlow(const Ind v) : V{v}
    {
        edge.resize(v);
        m_dist.resize(v);
        m_potential.resize(v);
        m_prev_v.resize(v);
        m_prev_e.resize(v);
    }

    void addEdge(const Ind from, const Ind to, const Capacity capacity, const Cost cost)
    {
        edge[from].push_back(Edge{from, to, (Ind)edge[to].size(), (Capacity)capacity, (Cost)cost, false});
        edge[to].push_back(Edge{to, from, (Ind)(edge[from].size() - 1), (Capacity)0, (Cost)(-cost), true});
    }

    T minCostFlow(const Ind s, const Ind t, T f)
    {
        using P = pair<Cost, Ind>;
        T res = 0;
        fill(m_potential.begin(), m_potential.end(), 0);

        // // Bellman-Ford(Replace this when DAG)
        // for (int i = 0; i < V; i++) {
        //     m_potential[i] = INF<T>;
        // }
        // m_potential[s] = 0;
        // bool no_negative_loop = true;
        // for (int i = 0; i < V; i++) {
        //     for (int v = 0; v < V; v++) {
        //         if (m_potential[v] != INF<T>) {
        //             for (const auto& e : edge[v]) {
        //                 if (e.capacity <= 0) {
        //                     continue;
        //                 }
        //                 if (m_potential[e.to] > m_potential[v] + e.cost) {
        //                     m_potential[e.to] = m_potential[v] + e.cost;
        //                     if (i == V - 1) {
        //                         m_potential[e.to] = -INF<T>;  // Confirm " -INF < min(possible_cost) * V "
        //                         no_negative_loop = false;
        //                     }
        //                 }
        //             }
        //         }
        //     }
        // }
        // if (not no_negative_loop) {
        //     // ????????¨?????????
        // }
        ////show(m_potential)

        while (f > 0) {
            // Dijkstra
            priority_queue<P, vector<P>, greater<P>> q;
            fill(m_dist.begin(), m_dist.end(), INF<T>);
            m_dist[s] = 0;
            q.push(make_pair(0, s));
            while (not q.empty()) {
                const P p = q.top();
                q.pop();
                const Ind v = p.second;
                if (m_dist[v] < p.first) {
                    continue;
                }
                for (Ind i = 0; i < edge[v].size(); i++) {
                    const auto& e = edge[v][i];
                    if (e.capacity > e.flow and m_dist[e.to] > m_dist[v] + e.cost + m_potential[v] - m_potential[e.to]) {
                        m_dist[e.to] = m_dist[v] + e.cost + m_potential[v] - m_potential[e.to];
                        m_prev_v[e.to] = v;
                        m_prev_e[e.to] = i;
                        q.push(make_pair(m_dist[e.to], e.to));
                    }
                }
            }
            if (m_dist[t] == INF<T>) {
                //                return -1;
                return res;
            }
            for (Ind v = 0; v < V; v++) {
                m_potential[v] += m_dist[v];
            }

            T d = f;
            for (Ind v = t; v != s; v = m_prev_v[v]) {
                const auto& e = edge[m_prev_v[v]][m_prev_e[v]];
                d = min(d, (T)(e.capacity - e.flow));
            }
            f -= d;
            res += d * m_potential[t];
            for (Ind v = t; v != s; v = m_prev_v[v]) {
                auto& e = edge[m_prev_v[v]][m_prev_e[v]];
                e.flow += d;
                edge[v][e.reverse].flow -= d;
            }
        }
        return res;
    }

    const Ind V;
    vector<vector<Edge>> edge;

private:
    vector<Cost> m_dist;
    vector<Cost> m_potential;
    vector<Ind> m_prev_v;
    vector<Ind> m_prev_e;
};

struct Ope {
    bool o;
    int r;
    int c;
};

int main()
{
    int n;
    cin >> n;
    vector<vector<int>> W(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> W[i][j];
        }
    }
    vector<vector<int>> E(n, vector<int>(n));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> E[i][j];
        }
    }

    vector<vector<bool>> use(n, vector<bool>(n, false));
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        for (int j = 0; j < n; j++) {
            use[i][j] = (s[j] == 'o');
        }
    }

    vector<vector<int>> c(n, vector<int>(n, 0));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (not use[i][j]) {
                c[i][j] = W[i][j];
            } else {
                for (int k = 0; k < n; k++) {
                    if (j == k) {
                        continue;
                    }
                    c[i][k] += E[i][j];
                }
                for (int k = 0; k < n; k++) {
                    if (i == k) {
                        continue;
                    }
                    c[k][j] += E[i][j];
                }
            }
        }
    }

    CostFlow flow(2 * n + 2);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            flow.addEdge(i, j + n, 1, c[i][j]);
        }
    }
    const int s = 2 * n;
    const int t = 2 * n + 1;
    for (int i = 0; i < n; i++) {
        flow.addEdge(s, i, 1, 0);
        flow.addEdge(n + i, t, 1, 0);
    }
    cout << flow.minCostFlow(s, t, n) << endl;

    set<int> node;
    node.insert(s);
    vector<Ope> op;
    for (int i = 0; i < n; i++) {
        for (const auto& e : flow.edge[i]) {
            if (e.is_reverse) {
                continue;
            }
            if (e.flow == 1) {
                if (not use[i][e.to - n]) {
                    op.push_back(Ope{false, i, e.to - n});
                }
            } else {
                if (use[i][e.to - n]) {
                    op.push_back(Ope{true, i, e.to - n});
                }
            }
        }
    }

    cout << op.size() << endl;
    for (const auto& o : op) {
        cout << o.r + 1 << " " << o.c + 1 << " " << (o.o ? "erase" : "write") << endl;
    }

    return 0;
}

Compiler output:
a.cc:14:19: error: 'numeric_limits' was not declared in this scope
   14 | constexpr T INF = numeric_limits<T>::max() / 10;
      |                   ^~~~~~~~~~~~~~
a.cc:14:35: error: expected primary-expression before '>' token
   14 | constexpr T INF = numeric_limits<T>::max() / 10;
      |                                   ^
a.cc:14:41: error: no matching function for call to 'max()'
   14 | constexpr T INF = numeric_limits<T>::max() / 10;
      |                                    ~~~~~^~
In file included from /usr/include/c++/14/string:51,
                 from /usr/include/c++/14/bits/locale_classes.h:40,
                 from /usr/include/c++/14/bits/ios_base.h:41,
                 from /usr/include/c++/14/ios:44,
                 from /usr/include/c++/14/ostream:40,
                 from /usr/include/c++/14/iostream:41,
                 from a.cc:1:
/usr/include/c++/14/bits/stl_algobase.h:257:5: note: candidate: 'template<class _Tp> constexpr const _Tp& std::max(const _Tp&, const _Tp&)'
  257 |     max(const _Tp& __a, const _Tp& __b)
      |     ^~~
/usr/include/c++/14/bits/stl_algobase.h:257:5: note:   candidate expects 2 arguments, 0 provided
/usr/include/c++/14/bits/stl_algobase.h:303:5: note: candidate: 'template<class _Tp, class _Compare> constexpr const _Tp& std::max(const _Tp&, const _Tp&, _Compare)'
  303 |     max(const _Tp& __a, const _Tp& __b, _Compare __comp)
      |     ^~~
/usr/include/c++/14/bits/stl_algobase.h:303:5: note:   candidate expects 3 arguments, 0 provided