Language: C++

#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;

    struct Edge{
        int src, dst, cap, cost, rev;
        Edge() {}
        Edge(int s, int d, int c, int cs, int r) : 
            src(s), dst(d), cap(c), cost(cs), rev(r) {}
    };

struct MinCostFlow{
    typedef pair<int, int> P;
    static const int INF = 100000000; 

    typedef vector<Edge> Node;
    typedef vector<Node> Graph;

    Graph G;

    MinCostFlow(int N) : G(N) {}

    void add_edge(int src, int dst, int cap, int cost){
        G[src].push_back(Edge(src, dst, cap, cost, G[dst].size()));
        G[dst].push_back(Edge(dst, src, 0, -cost, G[src].size() - 1));
    }

    int min_cost_flow(int s, int t, int f){
        int V = G.size();
        vector<int> h(V);
        vector<int> prevv(V), preve(V);
        int res = 0;
        while(f > 0){
            priority_queue<P, vector<P>, greater<P>> que;
            vector<int> dist(V, INF);
            dist[s] = 0;
            que.push(P(0, s));

            while(!que.empty()){
                P p = que.top(); que.pop();
                int v = p.second;
                if(dist[v] < p.first) continue;
                for(int i = 0; i < G[v].size(); i++){
                    Edge& e = G[v][i];
                    int ndist = dist[v] + e.cost + h[v] - h[e.dst];
                    if(e.cap > 0 && dist[e.dst] > ndist){
                        dist[e.dst] = ndist;
                        prevv[e.dst] = v;
                        preve[e.dst] = i;
                        que.push(P(ndist, e.dst));
                    }
                }
            }

            if(dist[t] == INF){
                return -1;
            }

            for(int v = 0; v < V; v++) h[v] += dist[v];

            int d = f;
            for(int v = t; v != s; v = prevv[v]){
                d = min(d, G[prevv[v]][preve[v]].cap);
            }

            f -= d;
            res += d * h[t];
            for(int v = t; v != s; v = prevv[v]){
                Edge& e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }

    vector<Edge> flow_edges(){
        vector<Edge> res;
        for(int i = 0; i < G.size(); i++){
            for(const auto& e : G[i]){
                if(e.cap == 0){
                    res.push_back(e);
                }
            }
        }
        return res;
    }
};

int main(){
    int N;
    while(cin >> N){
        int W[100][100];
        int E[100][100];
        REP(y, N) REP(x, N) cin >> W[y][x];
        REP(y, N) REP(x, N) cin >> E[y][x];
        string grid[100];
        REP(y, N) cin >> grid[y];

        MinCostFlow solver(N * N + 2);
        int Source = N * N;
        int Dist = Source + 1;
        REP(y, N) solver.add_edge(Source, y, 1, 0);
        REP(x, N) solver.add_edge(x + N, Dist, 1, 0);

        for(int y = 0; y < N; y++){
            for(int sx = 0; sx < N; sx++){
                int cost = 0;
                if(grid[y][sx] == '.'){
                    cost += W[y][sx];
                }
                for(int x = 0; x < N; x++){
                    if(x != sx && grid[y][x] == 'o'){
                        cost += E[y][x];
                    }
                }
                solver.add_edge(y, sx + N, 1, cost);
            }
        }

        int mincost = solver.min_cost_flow(Source, Dist, N);
        vector<Edge> edges = solver.flow_edges();
        vector<int> select(N);
        for(Edge e : edges){
            if(e.src < N){
                select[e.src] = e.dst - N;
            }
        }
        int count = 0;
        stringstream ss;
        for(int y = 0; y < N; y++){
            for(int x = 0; x < N; x++){
                if(select[y] == x && grid[y][x] == '.'){
                    ss << y + 1 << " " << x + 1 << " write" << endl;
                    count++;
                }
                if(select[y] != x && grid[y][x] == 'o'){
                    ss << y + 1 << " " << x + 1 << " erase" << endl;
                    count++;
                }
            }
        }
        cout << mincost << endl;
        cout << count << endl;
        cout << ss.str() << endl;
    }
    return 0;
}

Compiler output:
/usr/bin/ld: /tmp/ccqbh7EC.o: warning: relocation against `_ZN11MinCostFlow3INFE' in read-only section `.text._ZN11MinCostFlow13min_cost_flowEiii[_ZN11MinCostFlow13min_cost_flowEiii]'
/usr/bin/ld: /tmp/ccqbh7EC.o: in function `MinCostFlow::min_cost_flow(int, int, int)':
a.cc:(.text._ZN11MinCostFlow13min_cost_flowEiii[_ZN11MinCostFlow13min_cost_flowEiii]+0x10e): undefined reference to `MinCostFlow::INF'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status