Problem:
Draw in Straight Lines
You plan to draw a black-and-white painting on a rectangular canvas. The painting will be a grid array of pixels, either black or white. You can paint black or white lines or dots on the initially white canvas.
You can apply a sequence of the following two operations in any order.
Painting pixels on a horizontal or vertical line segment, single pixel wide and two or more pixel long, either black or white. This operation has a cost proportional to the length (the number of pixels) of the line segment multiplied by a specified coefficient in addition to a specified constant cost.
Painting a single pixel, either black or white. This operation has a specified constant cost.
You can overpaint already painted pixels as long as the following conditions are satisfied.
The pixel has been painted at most once before. Overpainting a pixel too many times results in too thick layers of inks, making the picture look ugly. Note that painting a pixel with the same color is also counted as overpainting. For instance, if you have painted a pixel with black twice, you can paint it neither black nor white anymore.
The pixel once painted white should not be overpainted with the black ink. As the white ink takes very long to dry, overpainting the same pixel black would make the pixel gray, rather than black. The reverse, that is, painting white over a pixel already painted black, has no problem.
Your task is to compute the minimum total cost to draw the specified image.
Input
The input consists of a single test case. The first line contains five integers $n$, $m$, $a$, $b$, and $c$, where $n$ ($1 \leq n \leq 40$) and $m$ ($1 \leq m \leq 40$) are the height and the width of the canvas in the number of pixels, and $a$ ($0 \leq a \leq 40$), $b$ ($0 \leq b \leq 40$), and $c$ ($0 \leq c \leq 40$) are constants defining painting costs as follows. Painting a line segment of length $l$ costs $al + b$ and painting a single pixel costs $c$. These three constants satisfy $c \leq a + b$.
The next $n$ lines show the black-and-white image you want to draw. Each of the lines contains a string of length $m$. The $j$-th character of the $i$-th string is ‘
#
’ if the color of the pixel in the $i$-th row and the $j$-th column is to be black, and it is ‘
.
’ if the color is to be white.
Output
Output the minimum cost.
Sample Input 1
3 3 1 2 3
.#.
###
.#.
Sample Output 1
10
Sample Input 2
2 7 0 1 1
###.###
###.###
Sample Output 2
3
Sample Input 3
5 5 1 4 4
..#..
..#..
##.##
..#..
..#..
Sample Output 3
24
Sample Input 4
7 24 1 10 10
###...###..#####....###.
.#...#...#.#....#..#...#
.#..#......#....#.#.....
.#..#......#####..#.....
.#..#......#......#.....
.#...#...#.#.......#...#
###...###..#........###.
Sample Output 4
256

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i, n) for(ll i=0; i <ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B>
bool chmax(A &a, B b) { return a < b && (a=b, true); }
template <class A, class B>
bool chmin(A &a, B b) { return b < a && (a=b, true); }

template<class C>
struct MaxFlow {
    C flow;
    V<char> dual; // false: S-side true: T-side
};

template<class C, class E>
struct MFExec {
    static constexpr C INF = numeric_limits<C>::max();
    C eps;
    V<V<E>>& g;
    int s, t;
    V<int> level, iter;

    C dfs(int v, C f) {
        if (v == t) return f;
        C res = 0;
        for (int& i = iter[v]; i < int(g[v].size()); i++) {
            E& e = g[v][i];
            if (e.cap <= eps || level[v] >= level[e.to]) continue;
            C d = dfs(e.to, min(f, e.cap));
            e.cap -= d;
            g[e.to][e.rev].cap += d;
            res += d;
            f -= d;
            if (f == 0) break;
        }
        return res;
    }

    MaxFlow<C> info;
    MFExec(V<V<E>>& _g, int _s, int _t, C _eps)
        : eps(_eps), g(_g), s(_s), t(_t) {
        int N = int(g.size());

        C& flow = (info.flow = 0);
        while (true) {
            queue<int> que;
            level = V<int>(N, -1);
            level[s] = 0;
            que.push(s);
            while (!que.empty()) {
                int v = que.front(); que.pop();
                for (E e: g[v]) {
                    if (e.cap <= eps || level[e.to] >= 0) continue;
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
            if (level[t] == -1) break;
            iter = V<int>(N, 0);
            while (true) {
                C f = dfs(s, INF);
                if (!f) break;
                flow += f;
            }
        }
        for (int i = 0; i < N; i++) info.dual.push_back(level[i] == -1);
    }
};

template<class C, class E>
MaxFlow<C> get_mf(V<V<E>>& g, int s, int t, C eps) {
    return MFExec<C, E>(g, s, t, eps).info;
}

struct Edge { int to, rev; ll cap; };

void testcase(){
    ll H, W, A, B, C; cin >> H >> W >> A >> B >> C;
    V<string> G(H); for(auto& g : G) cin >> g;
    V<V<Edge>> graph(H*W*4+2);
    ll src = H * W * 4;
    ll snk = src + 1;
    auto Idx = [&](ll y, ll x){ return (y * W + x) * 4; };

    auto add_edge = [&](int from, int to, ll cap) {
        graph[from].push_back({to, int(graph[to].size()), cap});
        graph[to].push_back({from, int(graph[from].size())-1, 0});
    };
    
    REP(x,W) add_edge(src, Idx(0,x) + 0, B);
    REP(y,H-1) REP(x,W) add_edge(Idx(y,x) + 0, Idx(y+1,x) + 0, B);
    REP(y,H) REP(x,W) add_edge(src, Idx(y,x) + 0, A);
    REP(y,H) add_edge(Idx(y,W-1) + 1, snk, B);
    REP(y,H) REP(x,W-1) add_edge(Idx(y,x) + 1, Idx(y,x+1) + 1, B);
    REP(y,H) REP(x,W) add_edge(Idx(y,x) + 1, snk, A);
    REP(y,H) REP(x,W) if(G[y][x] == '.') add_edge(Idx(y,x) + 1, Idx(y,x) + 0, INF);
    REP(y,H) REP(x,W) if(G[y][x] == '#') add_edge(Idx(y,x) + 0, Idx(y,x) + 1, C);
    REP(x,W) add_edge(Idx(H-1,x) + 2, snk, B);
    REP(y,H-1) REP(x,W) add_edge(Idx(y,x) + 2, Idx(y+1,x) + 2, B);
    REP(y,H) REP(x,W) add_edge(Idx(y,x) + 2, snk, G[y][x] == '.' ? A : INF);
    REP(y,H) add_edge(src, Idx(y,0) + 3, B);
    REP(y,H) REP(x,W-1) add_edge(Idx(y,x) + 3, Idx(y,x+1) + 3, B);
    REP(y,H) REP(x,W) add_edge(src, Idx(y,x) + 3, G[y][x] == '.' ? A : INF);
    REP(y,H) REP(x,W) if(G[y][x] == '.') add_edge(Idx(y,x) + 3, Idx(y,x) + 0, C);
    REP(y,H) REP(x,W) if(G[y][x] == '.') add_edge(Idx(y,x) + 1, Idx(y,x) + 2, C);

    cout << get_mf(graph, src, snk, 0ll).flow << "\n";
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    testcase();
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4340
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define sar(a,n) {cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl;}

using namespace std;

template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}
template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}
template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>&m){for(auto&e:m)o<<e<<" ";return o;}
template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}
void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}
template<typename S,typename T,typename U>
struct TRI{S fi;T se;U th;TRI(){}TRI(S f,T s,U t):fi(f),se(s),th(t){}
bool operator<(const TRI&_)const{return(fi==_.fi)?((se==_.se)?(th<_.th):(se<_.se)):(fi<_.fi);}};
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,TRI<S,T,U>&t){return o<<"{"<<t.fi<<","<<t.se<<","<<t.th<<"}";}

typedef pair<int, int> P;
typedef pair<ll, ll> pll;
typedef TRI<int, int, int> tri;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef vector<P> vp;
typedef vector<double> vd;
typedef vector<string> vs;

template<typename T> class Dinic {
private:
    int V;
    vector<int> level,iter;
    void bfs(int s) {
        fill(level.begin(),level.end(),-1);
        queue<int> que;
        level[s] = 0;
        que.push(s);
        while(!que.empty()){
            int v = que.front();
            que.pop();
            for(auto& e : G[v]){
                if(e.cap > 0 && level[e.to] < 0){
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }
    }
    T dfs(int v,int t,T f) {
        if(v==t){
            return f;
        }
        for(int& i = iter[v]; i < (int)G[v].size(); i++){
            edge& e = G[v][i];
            if(e.cap > 0 && level[v] < level[e.to]){
                T d = dfs(e.to,t,min(f,e.cap));
                if(d > 0){
                    e.cap -= d;
                    G[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }

public:
    struct edge{
        int to;
        T cap;
        int rev;
    };
    vector<vector<edge> > G;

    Dinic(int node_size) : V(node_size), level(V), iter(V), G(V){}
    //辺を張る
    void add_edge(int from, int to, T cap) {
        G[from].push_back((edge){to,cap,(int)G[to].size()});
        G[to].push_back((edge){from,(T)0,(int)G[from].size()-1});
    }
    //最大流を計算
    T solve(int s, int t) {
        T flow = 0;
        for(;;){
            bfs(s);
            if(level[t] < 0) return flow;
            fill(iter.begin(),iter.end(),0);
            T f;
            while((f=dfs(s,t,numeric_limits<T>::max())) > 0){
                flow += f;
            }
        }
    }
};

const int MAX_N = 45;
string S[MAX_N];
int n, m, a, b, c;

int trans(int x, int y, int z){
    return x * n * m + y * m + z;
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cin >> n >> m >> a >> b >> c;
    rep(i,n){
        cin >> S[i];
    }
    Dinic<ll> dn(4*n*m+2);
    const ll inf = numeric_limits<ll>::max() / 10;
    const int s = 4*n*m, t = 4*n*m+1;
    // 0: 縦に黒で塗る, 1: 横に黒で塗らない, 2: 縦に白で塗らない, 3: 横に白で塗る
    rep(i,n){
        rep(j,m){
            dn.add_edge(trans(0, i, j), t, a);
            if(i < n-1) dn.add_edge(trans(0, i, j), trans(0, i+1, j), b);
            else dn.add_edge(trans(0, i, j), t, b);
            dn.add_edge(s, trans(1, i, j), a);
            if(j < m-1) dn.add_edge(trans(1, i, j+1), trans(1, i, j), b);
            else dn.add_edge(s, trans(1, i, j), b);
            dn.add_edge(s, trans(2, i, j), a);
            if(i < n-1) dn.add_edge(trans(2, i+1, j), trans(2, i, j), b);
            else dn.add_edge(s, trans(2, i, j), b);
            dn.add_edge(trans(3, i, j), t, a);
            if(j < m-1) dn.add_edge(trans(3, i, j), trans(3, i, j+1), b);
            else dn.add_edge(trans(3, i, j), t, b);
            if(S[i][j] == '#'){
                // 縦に黒塗らないかつ横に黒塗らないならこはコスト c で塗る必要がある
                dn.add_edge(trans(1, i, j), trans(0, i, j), c);
                // 白の上から黒では塗れないので白で塗るのを禁止
                dn.add_edge(s, trans(2, i, j), inf);
                dn.add_edge(trans(3, i, j), t, inf);
            }else{
                // 縦, 横に黒で塗る場合, その後白で塗ることになり 3 重塗りで禁止
                dn.add_edge(trans(0, i, j), trans(1, i, j), inf);
                // 縦に黒塗るかつ横に白に塗らないならそこはコスト c で塗る必要がある(縦に白で塗るのはコスト最小化的にない)
                dn.add_edge(trans(0, i, j), trans(3, i, j), c);
                // 横に黒塗るかつ縦に白に塗らないならそこはコスト c で塗る必要がある(横に白で塗るのはコスト最小化的にない)
                dn.add_edge(trans(2, i, j), trans(1, i, j), c);
                // 縦, 横に白, 縦 or 横に黒を塗る場合の 3 重塗りはコスト最小化的に起きないので禁止する必要なし
            }
        }
    }
    cout << dn.solve(s, t) << "\n";
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4692
final_rank: 13

code_snippet: #include<bits/stdc++.h>
#define ll long long
#define gmax(x,y) x=max(x,y)
#define gmin(x,y) x=min(x,y)
#define F first
#define S second
#define P pair
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i<b;i++)
#define V vector
#define RE return
#define ALL(a) a.begin(),a.end()
#define MP make_pair
#define PB emplace_back
#define PF push_front
#define FILL(a,b) memset(a,b,sizeof(a))
#define lwb lower_bound
#define upb upper_bound
#define lc (x<<1)
#define rc ((x<<1)|1)
#define sz(x) ((int)x.size())
#define pc putchar
using namespace std;
int INF=1e9;
struct max_flow{
	struct node{int to,cap,rev;};
	node edge(int to1,int cap1,int rev1){
		node re;
		re.to=to1;
		re.cap=cap1;
		re.rev=rev1;
		RE re;
	}
	V<node> g[7005];
	int d[7005],cur[7005],vis[7005];
	void add(int u,int v,int cap){
		g[u].PB(edge(v,cap,g[v].size()));
		g[v].PB(edge(u,0,g[u].size()-1));
	} 
	void clear(int n){
		FOR(i,0,n)g[i].clear();
	}
	int q[7005];
	void bfs(int s){
		FILL(d,-1);
		d[s]=0;
		int st=1,ed=0;
		q[++ed]=s;
		int cur;
		while(st<=ed){
			cur=q[st++];
			for(auto &e:g[cur]){
				if(e.cap>0&&d[e.to]<0){
					d[e.to]=d[cur]+1;
					q[++ed]=e.to;
				}
			}
		}
	}
	int dfs(int v,int t,int f){
		int dist,re=0;
		if(v==t||!f)RE f;
		rep(i,cur[v],(int)g[v].size()){
			auto &e=g[v][i];
			if(e.cap>0&&d[v]<d[e.to]){
				dist=dfs(e.to,t,min(f,e.cap));
				if(dist>0){
					e.cap-=dist;
					g[e.to][e.rev].cap+=dist;
					re+=dist;
					f-=dist;
					if(!f)break;
				}
			}
			cur[v]++;
		}
		if(!re)d[v]=-1;
		RE re;
	}
	int get(int s,int t){
		int flow=0,f;
		while(1){
			bfs(s);
			if(d[t]<0)break;
			FILL(cur,0);
			f=dfs(s,t,INF);flow+=f;
		}
		FILL(vis,0);
		queue<int> q;
		q.emplace(s);
		vis[s]=1;
		while(!q.empty()){
			int now=q.front();q.pop();
			for(auto u:g[now])if(u.cap&&!vis[u.to]){
				vis[u.to]=1;
				q.emplace(u.to);
			}
		}
		RE flow;
	}
}mf;
int n,m,a,b,c;
char C[45][45];
int ithW[45][45],itlW[45][45],ithB[45][45],itlB[45][45];
int cnt=0;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m>>a>>b>>c;
	FOR(i,1,n)FOR(j,1,m)cin>>C[i][j];
	int S=0;
	FOR(i,1,n)FOR(j,1,m){
		ithW[i][j]=++cnt;itlW[i][j]=++cnt;
		ithB[i][j]=++cnt;itlB[i][j]=++cnt;
	}
	int T=++cnt;
	FOR(i,1,n)FOR(j,1,m){
		if(C[i][j]=='#'){
			mf.add(itlW[i][j],T,INF);
			mf.add(S,ithW[i][j],INF);
			mf.add(itlB[i][j],ithB[i][j],c);
		}else{
			mf.add(ithB[i][j],itlB[i][j],INF);
			mf.add(ithB[i][j],itlW[i][j],c);
			mf.add(ithW[i][j],itlB[i][j],c);
		}
	}
	FOR(i,1,m)mf.add(itlW[1][i],T,b),mf.add(S,itlB[1][i],b);
	FOR(i,1,n)mf.add(S,ithW[i][1],b),mf.add(ithB[i][1],T,b);
	FOR(i,2,n)FOR(j,1,m){
		mf.add(itlW[i][j],itlW[i-1][j],b);
		mf.add(itlB[i-1][j],itlB[i][j],b);
	}
	FOR(i,1,n)FOR(j,2,m){
		mf.add(ithW[i][j-1],ithW[i][j],b);
		mf.add(ithB[i][j],ithB[i][j-1],b);
	}
	FOR(i,1,n)FOR(j,1,m){
		mf.add(S,ithW[i][j],a);
		mf.add(ithB[i][j],T,a);
		mf.add(itlW[i][j],T,a);
		mf.add(S,itlB[i][j],a);
	}
	cout<<mf.get(S,T)<<"\n";
	RE 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4608
final_rank: 11

code_snippet: #include<bits/stdc++.h>
#define ll long long
#define gmax(x,y) x=max(x,y)
#define gmin(x,y) x=min(x,y)
#define F first
#define S second
#define P pair
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i<b;i++)
#define V vector
#define RE return
#define ALL(a) a.begin(),a.end()
#define MP make_pair
#define PB emplace_back
#define PF push_front
#define FILL(a,b) memset(a,b,sizeof(a))
#define lwb lower_bound
#define upb upper_bound
#define lc (x<<1)
#define rc ((x<<1)|1)
#define sz(x) ((int)x.size())
#define pc putchar
using namespace std;
int INF=1e9;
struct max_flow{
	struct node{int to,cap,rev;};
	node edge(int to1,int cap1,int rev1){
		node re;
		re.to=to1;
		re.cap=cap1;
		re.rev=rev1;
		RE re;
	}
	V<node> g[7005];
	int d[7005],cur[7005],vis[7005];
	void add(int u,int v,int cap){
		g[u].PB(edge(v,cap,g[v].size()));
		g[v].PB(edge(u,0,g[u].size()-1));
	} 
	void clear(int n){
		FOR(i,0,n)g[i].clear();
	}
	int q[7005];
	void bfs(int s){
		FILL(d,-1);
		d[s]=0;
		int st=1,ed=0;
		q[++ed]=s;
		int cur;
		while(st<=ed){
			cur=q[st++];
			for(auto &e:g[cur]){
				if(e.cap>0&&d[e.to]<0){
					d[e.to]=d[cur]+1;
					q[++ed]=e.to;
				}
			}
		}
	}
	int dfs(int v,int t,int f){
		int dist,re=0;
		if(v==t||!f)RE f;
		rep(i,cur[v],(int)g[v].size()){
			auto &e=g[v][i];
			if(e.cap>0&&d[v]<d[e.to]){
				dist=dfs(e.to,t,min(f,e.cap));
				if(dist>0){
					e.cap-=dist;
					g[e.to][e.rev].cap+=dist;
					re+=dist;
					f-=dist;
					if(!f)break;
				}
			}
			cur[v]++;
		}
		if(!re)d[v]=-1;
		RE re;
	}
	int get(int s,int t){
		int flow=0,f;
		while(1){
			bfs(s);
			if(d[t]<0)break;
			FILL(cur,0);
			f=dfs(s,t,INF);flow+=f;
		}
		FILL(vis,0);
		queue<int> q;
		q.emplace(s);
		vis[s]=1;
		while(!q.empty()){
			int now=q.front();q.pop();
			for(auto u:g[now])if(u.cap&&!vis[u.to]){
				vis[u.to]=1;
				q.emplace(u.to);
			}
		}
		RE flow;
	}
}mf;
int n,m,a,b,c;
char C[45][45];
int ithW[45][45],itlW[45][45],ithB[45][45],itlB[45][45];
int cnt=0;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m>>a>>b>>c;
	FOR(i,1,n)FOR(j,1,m)cin>>C[i][j];
	int S=0;
	FOR(i,1,n)FOR(j,1,m){
		ithW[i][j]=++cnt;itlW[i][j]=++cnt;
		ithB[i][j]=++cnt;itlB[i][j]=++cnt;
	}
	int T=++cnt;
	FOR(i,1,n)FOR(j,1,m){
		if(C[i][j]=='#'){
			mf.add(itlW[i][j],T,INF);
			mf.add(S,ithW[i][j],INF);
			mf.add(itlB[i][j],ithB[i][j],c);
		}else{
			mf.add(ithB[i][j],itlB[i][j],INF);
			mf.add(ithB[i][j],itlW[i][j],c);
			mf.add(ithW[i][j],itlB[i][j],c);
		}
	}
	FOR(i,1,m)mf.add(itlW[1][i],T,b),mf.add(S,itlB[1][i],b);
	FOR(i,1,n)mf.add(S,ithW[i][1],b),mf.add(ithB[i][1],T,b);
	FOR(i,2,n)FOR(j,1,m){
		mf.add(itlW[i][j],itlW[i-1][j],b);
		mf.add(itlB[i-1][j],itlB[i][j],b);
	}
	FOR(i,1,n)FOR(j,2,m){
		mf.add(ithW[i][j-1],ithW[i][j],b);
		mf.add(ithB[i][j],ithB[i][j-1],b);
	}
	FOR(i,1,n)FOR(j,1,m){
		mf.add(S,ithW[i][j],a);
		mf.add(ithB[i][j],T,a);
		mf.add(itlW[i][j],T,a);
		mf.add(S,itlB[i][j],a);
	}
	cout<<mf.get(S,T)<<"\n";
	RE 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4596
final_rank: 10

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

#define PB push_back
// #define int long long
#define ll long long
#define vi vector<int>
#define siz(a) ((int)((a).size()))
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)

const int N = 40, M = 1e6, inf = 1e9;
int a, b, A, B, C;
char p[N + 5][N + 5];

struct flow {
	int head[M + 5], top, dep[M + 5], cur[M + 5], S, T;
	struct road {
		int lst, v, w;
	} s[M + 5];

	void init() {
		top = 1;
		memset(head, 0, sizeof(head));
	}
	void add(int n, int m, int k) {
		s[++top] = (road) {head[n], m, k};
		head[n] = top;
		s[++top] = (road) {head[m], n, 0};
		head[m] = top;
	}
	bool bfs() {
		memset(dep, 0, sizeof(dep));
		memcpy(cur, head, sizeof(cur));
		dep[S] = 1;
		queue<int> qu;
		qu.push(S);
		while(siz(qu)) {
			int u = qu.front();
			qu.pop();
			for(int i = head[u]; i; i = s[i].lst) {
				int v = s[i].v, w = s[i].w;
				if(dep[v] || !w) continue;
				dep[v] = dep[u] + 1;
				qu.push(v);
			}
		}
		return dep[T];
	}
	int dfs(int n, int mx) {
		if(n == T) return mx;
		int res = 0;
		for(int i = cur[n]; i; i = s[i].lst) {
			cur[n] = i;
			int v = s[i].v, w = s[i].w;
			if(dep[v] != dep[n] + 1 || !w) continue;
			int tmp = dfs(v, min(mx, w));
			mx -= tmp;
			res += tmp;
			s[i].w -= tmp;
			s[i ^ 1].w += tmp;
			if(!mx) break;
		}
		if(!res) dep[n] = -1;
		return res;
	}
	int dinic() {
		int res = 0;
		while(bfs()) while(int tmp = dfs(S, inf)) {
			res += tmp;
		}
		return res;
	}
} F;

int id(int i, int j, int o) {return (i - 1) * b + j + o * a * b;}

signed main() {
	// freopen("in.in", "r", stdin);
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> a >> b >> A >> B >> C;
	rep(i, 1, a) cin >> (p[i] + 1);
	F.init();
	F.S = 0, F.T = id(a, b, 3) + 1;
	// 0：行黑 1：列黑 2：行白 3：列白
	// B : 0 1
	// W : 3 2
	#define S F.S
	#define T F.T
	rep(i, 1, a) rep(j, 1, b) {
		F.add(id(i, j, 2), id(i, j, 0), inf);
		F.add(id(i, j, 1), id(i, j, 3), inf);
		F.add(S, id(i, j, 0), A);
		F.add(S, id(i, j, 3), A);
		F.add(id(i, j, 1), T, A);
		F.add(id(i, j, 2), T, A);
		if(p[i][j] == '#') {
			F.add(id(i, j, 2), T, inf);
			F.add(S, id(i, j, 3), inf);
			F.add(id(i, j, 0), id(i, j, 1), C);
		}
		else {
			F.add(id(i, j, 1), id(i, j, 0), inf);
			F.add(id(i, j, 3), id(i, j, 0), C);
			F.add(id(i, j, 1), id(i, j, 2), C);
		}
		if(i == 1) {
			F.add(id(i, j, 1), T, B);
			F.add(S, id(i, j, 3), B);
		}
		else {
			F.add(id(i, j, 1), id(i - 1, j, 1), B);
			F.add(id(i - 1, j, 3), id(i, j, 3), B);
		}
		if(j == 1) {
			F.add(S, id(i, j, 0), B);
			F.add(id(i, j, 2), T, B);
		}
		else {
			F.add(id(i, j - 1, 0), id(i, j, 0), B);
			F.add(id(i, j, 2), id(i, j - 1, 2), B);
		}
	}
	cout << F.dinic() << "\n";
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 15764
final_rank: 19

code_snippet: #include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 40 + 5, inf = 1e9;
char f[N][N]; int n, m, a, b, c; 

namespace Flow {
  #define Next(i, u) for (int i = cur[u]; i; i = e[i].next)
  const int M = 6400 + 5, E = 32000 + 5; 
  struct edge { int v, w, next; } e[E << 1];
  int s, t, tot = 1, h[M], cur[M], dep[M];  

  void add (int u, int v, int w) {
    e[++tot] = (edge){v, w, h[u]}, h[u] = tot;
    e[++tot] = (edge){u, 0, h[v]}, h[v] = tot;   
  }
  bool bfs (int s, int t) {
    rep(i, s, t) cur[i] = h[i], dep[i] = inf; 
    queue <int> Q; Q.push(s), dep[s] = 0; 
    while (!Q.empty()) {
      int u = Q.front(); Q.pop(); 
      Next(i, u) {
        int v = e[i].v; if(!e[i].w || dep[v] < inf) continue ; 
        dep[v] = dep[u] + 1, Q.push(v); 
      }
    }
    return dep[t] < inf; 
  } 
  int dfs (int u, int lim) {
    if(u == t) return lim; 
    int flow = 0, rflow = 0; 
    Next(i, u) {
      int v = e[i].v; cur[u] = i; 
      if(dep[v] == dep[u] + 1 && e[i].w && (rflow = dfs(v, min(e[i].w, lim)))) {
        flow += rflow, lim -= rflow, e[i].w -= rflow, e[i ^ 1].w += rflow; 
        if(!lim) break ; 
      }
    }
    return flow; 
  }
  int dinic (int S, int T) {
    int ans = 0; s = S, t = T; 
    while (bfs(s, t)) ans += dfs(s, inf); 
    return ans; 
  }
}
int id (int x, int y, int o) {
  return o * n * m + (x - 1) * m + y; 
}

int main () {
  cin >> n >> m >> a >> b >> c; 
  rep(i, 1, n) scanf("%s", f[i] + 1); 
  int s = 0, t = 4 * n * m + 1; 
  rep(i, 1, n) rep(j, 1, m) {
    Flow :: add(s, id(i, j, 0), a), Flow :: add(id(i, j, 0), t, 0);
    Flow :: add(s, id(i, j, 1), 0), Flow :: add(id(i, j, 1), t, a);
    Flow :: add(s, id(i, j, 2), 0), Flow :: add(id(i, j, 2), t, a);
    Flow :: add(s, id(i, j, 3), a), Flow :: add(id(i, j, 3), t, 0);
    Flow :: add(id(i, j, 1), id(i, j, 0), inf); 
    Flow :: add(id(i, j, 2), id(i, j, 3), inf); 
    if(f[i][j] == '#') {
      Flow :: add(s, id(i, j, 0), inf), Flow :: add(id(i, j, 2), t, inf);
      Flow :: add(id(i, j, 3), id(i, j, 1), c);  
    } else {
      Flow :: add(id(i, j, 1), id(i, j, 3), inf); 
      Flow :: add(id(i, j, 0), id(i, j, 3), c); 
      Flow :: add(id(i, j, 1), id(i, j, 2), c); 
    }
    if(j == 1) Flow :: add(s, id(i, j, 0), b), Flow :: add(id(i, j, 1), t, b); 
    else {
      Flow :: add(id(i, j - 1, 0), id(i, j, 0), b); 
      Flow :: add(id(i, j, 1), id(i, j - 1, 1), b); 
    }
    if(i == 1) Flow :: add(id(i, j, 2), t, b), Flow :: add(s, id(i, j, 3), b);
    else {
      Flow :: add(id(i, j, 2), id(i - 1, j, 2), b);
      Flow :: add(id(i - 1, j, 3), id(i, j, 3), b);  
    } 
  }
  printf("%d\n", Flow :: dinic(s, t)); 
  return 0; 
}
accuracy: 1
time_ms: 10
memory_kb: 4304
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
using namespace std;

int n,m,a,b,c,s,t,tot,br[50][50],bc[50][50],wr[50][50],wc[50][50];
char ch[50][50];
vector<pair<pair<int,int>,int> > g[6410];
int lvl[6410],r[6410];

inline void add_edge(int x,int y,int c)
{
	g[x].push_back(make_pair(make_pair(y,c),g[y].size()));
	g[y].push_back(make_pair(make_pair(x,0),g[x].size()-1));
}

inline void bfs(int x)
{
	memset(lvl,-1,sizeof(lvl));
	queue<int> q;
	lvl[x]=0;
	q.push(x);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<(int)g[u].size();i++){
			pair<pair<int,int>,int> e=g[u][i];
			if(e.first.second>0&&lvl[e.first.first]==-1){
				lvl[e.first.first]=lvl[u]+1;
				q.push(e.first.first);
			}
		}
	}
}

inline int dfs(int now,int cap)
{ 
	if(now==t){
		return cap;
	}
	for(int i=r[now];i<(int)g[now].size();i++,r[now]++){
		pair<pair<int,int>,int> e=g[now][i];
		if(e.first.second>0&&(lvl[now]<lvl[e.first.first])){
			int dis=dfs(e.first.first,min(cap,e.first.second));
			if(dis>0){
				g[now][i].first.second-=dis;
				g[e.first.first][e.second].first.second+=dis;
				return dis;
			}
		}
	}
	return 0;
}

inline int max_flow()
{
	int flow=0;
	while(true){
		bfs(s);
		if(lvl[t]==-1) return flow;
		memset(r,0,sizeof(r));
		int f=dfs(s,INF);
		while(f>0){
			flow+=f;
			f=dfs(s,INF);
		}
	}
}

signed main()
{
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n>>m>>a>>b>>c;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>ch[i][j];
			br[i][j]=++tot;bc[i][j]=++tot;
			wr[i][j]=++tot;wc[i][j]=++tot;
		}
	}
	s=tot+1;t=tot+2;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(j<m){
				add_edge(br[i][j+1],br[i][j],b);
				add_edge(wr[i][j],wr[i][j+1],b);
			}
			else{
				add_edge(s,br[i][j],b);
				add_edge(wr[i][j],t,b);
			}
			if(i<n){
				add_edge(bc[i][j],bc[i+1][j],b);
				add_edge(wc[i+1][j],wc[i][j],b);
			}
			else{
				add_edge(bc[i][j],t,b);
				add_edge(s,wc[i][j],b);
			}
			if(ch[i][j]=='#'){
				add_edge(s,br[i][j],a);
				add_edge(br[i][j],bc[i][j],c);
				add_edge(bc[i][j],t,a);
				add_edge(s,wc[i][j],INF);
				add_edge(wr[i][j],t,INF);
			}
			else{
				add_edge(s,br[i][j],a);
				add_edge(bc[i][j],br[i][j],INF);
				add_edge(bc[i][j],t,a);
				add_edge(s,wc[i][j],a);
				add_edge(wc[i][j],br[i][j],c);
				add_edge(bc[i][j],wr[i][j],c);
				add_edge(wr[i][j],t,a);
				add_edge(wr[i][j],br[i][j],INF);
				add_edge(bc[i][j],wc[i][j],INF);
			}
		}
	}
	cout<<max_flow()<<'\n';
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4404
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
struct Dinic{
	struct edge{
		int to,cap,rev;
		edge(int to,int cap,int rev):to(to),cap(cap),rev(rev){} 
	};
	vector<edge>g[6404];
	int lev[6404],iter[6404],ans;
	void add(int u,int v,int w){
		g[u].push_back(edge(v,w,g[v].size()));
		g[v].push_back(edge(u,0,g[u].size()-1));
	}
	void bfs(int s){
		memset(lev,-1,sizeof(lev));
		queue<int>que;lev[s]=0,que.push(s);
		while(!que.empty()){
			int u=que.front();que.pop();
			for(int i=0;i<g[u].size();i++){
				edge&x=g[u][i];
				if(x.cap==0||lev[x.to]>=0)continue;
				lev[x.to]=lev[u]+1,que.push(x.to);
			}
		}
	}
	int dfs(int x,int t,int F){
		if(x==t)return F;
		for(int &i=iter[x];i<g[x].size();i++){
			edge &e=g[x][i];
			if(lev[e.to]>lev[x]&&e.cap>0){
				int d=dfs(e.to,t,min(F,e.cap));
				if(d>0){
					e.cap-=d;
					g[e.to][e.rev].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	int maxflow(int s,int t){
		int ret=0;
		for(;;){
			bfs(s);
			if(lev[t]<0)return ret;
			memset(iter,0,sizeof(iter));
			int f;
			while((f=dfs(s,t,INF))>0)ret+=f; 
		}
	}
}Gr;
int h,w,a,b,c,br[44][44],bc[44][44],wr[44][44],wc[44][44];
char s[44][44];int tot;
int main(){
	scanf("%d%d%d%d%d",&h,&w,&a,&b,&c);int t=h*w*4+1;
	for(int i=1;i<=h;i++)scanf("%s",s[i]+1);
	for(int i=1;i<=h;i++)for(int j=1;j<=w;j++)
		br[i][j]=++tot,bc[i][j]=++tot,wr[i][j]=++tot,wc[i][j]=++tot;
	for(int i=1;i<=h;i++)for(int j=1;j<=w;j++){
		Gr.add(0,br[i][j],a),Gr.add(bc[i][j],t,a);
		Gr.add(0,wc[i][j],a),Gr.add(wr[i][j],t,a);
		Gr.add(wr[i][j],br[i][j],INF),Gr.add(bc[i][j],wc[i][j],INF);
		if(s[i][j]=='#')Gr.add(wr[i][j],t,INF),Gr.add(0,wc[i][j],INF),Gr.add(br[i][j],bc[i][j],c);
		else Gr.add(bc[i][j],br[i][j],INF),Gr.add(wc[i][j],br[i][j],c),Gr.add(bc[i][j],wr[i][j],c);
		if(j==1)Gr.add(0,br[i][j],b),Gr.add(wr[i][j],t,b);
		else Gr.add(br[i][j-1],br[i][j],b),Gr.add(wr[i][j],wr[i][j-1],b);
		if(i==1)Gr.add(bc[i][j],t,b),Gr.add(0,wc[i][j],b);
		else Gr.add(bc[i][j],bc[i-1][j],b),Gr.add(wc[i-1][j],wc[i][j],b);
	}
	printf("%d\n",Gr.maxflow(0,t));
}
accuracy: 1
time_ms: 10
memory_kb: 4636
final_rank: 12

code_snippet: #include<bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < n; ++i)
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;

struct {
	int cn, hd[1000100], cur[1000100]; int dis[1000100];
	int ce, nxt[1000100], to[1000100]; int cap[1000100];
	void clr(int n){
		cn = n, ce = 0;
		fill(hd, hd+cn, -1);
	}
	void ae(int f, int t, int c){
		//cout << "ae " << f << " " << t << " " << c << endl;
		nxt[ce] = hd[f], to[ce] = t, cap[ce] = c, hd[f] = ce++;
		nxt[ce] = hd[t], to[ce] = f, cap[ce] = 0, hd[t] = ce++;
	}
	bool bfs(int S, int T){
		fill(dis, dis+cn, inf);
		dis[S] = 0;
		queue<int> q; q.emplace(S);
		while(!q.empty()){
			int u = q.front(); q.pop();
			for(int eid = hd[u]; eid >= 0; eid = nxt[eid]){
				int t = to[eid];
				if(cap[eid] && dis[t] > dis[u] + 1)
					dis[t] = dis[u] + 1, q.emplace(t);
			}
		}
		return dis[T] < inf;
	}
	int dfs(int u, int dest, int flow){
		if(u == dest) return flow;
		int nf = 0;
		for(int &eid = cur[u]; eid >= 0; eid = nxt[eid]){
			int t = to[eid];
			if(cap[eid] && dis[t] == dis[u] + 1){
				int ret = dfs(t, dest, min(cap[eid], flow-nf));
				nf += ret, cap[eid] -= ret, cap[eid^1] += ret;
				if(nf == flow)
					break;
			}
		}
		return nf;
	}
	int mf(int S, int T){
		int ret = 0;
		while(bfs(S, T)){
			rep(i, cn) cur[i] = hd[i];
			ret += dfs(S, T, inf);
		}
		return ret;
	}
} mf;

int n, m, a, b, c;
string s[44];
inline int id(int tp, int i, int j){ return 2 + tp*(n+1)*(m+1) + i*(m+1) + j; } // add 2+

int main(){
	ios::sync_with_stdio(false);

	cin >> n >> m >> a >> b >> c;
	mf.clr(2 + 4*(n+1)*(m+1));
	rep(i, n)
		cin >> s[i];

	for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j){
		//cout << "----------" << i << " " << j << "-------------" << endl;
		mf.ae(0, id(0, i, j), a);
		mf.ae(id(1, i, j), 1, a);
		if(s[i-1][j-1] == '#'){
			mf.ae(id(0, i, j), id(1, i, j), c);
			mf.ae(0, id(2, i, j), inf); // add these
			mf.ae(id(3, i, j), 1, inf);
		} else {
			mf.ae(id(1, i, j), id(0, i, j), inf); // add this
			mf.ae(0, id(2, i, j), a);
			mf.ae(id(3, i, j), 1, a);
			mf.ae(id(2, i, j), id(0, i, j), c);
			mf.ae(id(1, i, j), id(3, i, j), c);
		}
	}
	rep(i, n+1) rep(j, m+1) if(!i || !j){
		mf.ae(0, id(0, i, j), inf), mf.ae(id(3, i, j), 1, inf);
		mf.ae(id(1, i, j), 1, inf), mf.ae(0, id(2, i, j), inf);
	}

	rep(i, n+1) rep(j, m){
		mf.ae(id(0, i, j), id(0, i, j+1), b);
		mf.ae(id(3, i, j+1), id(3, i, j), b); // swap 2 3
	}
	rep(i, n) rep(j, m+1){
		mf.ae(id(1, i+1, j), id(1, i, j), b);
		mf.ae(id(2, i, j), id(2, i+1, j), b);
	}

	cout << mf.mf(0, 1) << "\n";

	//rep(i, mf.cn)
	//	if(mf.dis[i] < inf){
	//		cout << "to: " << (i-2) / (n*m) << " " << (i-2) % (n*m) / m << " " << (i-2) % (n*m) % m << endl;
	//	}

	return 0;
}

// by zxb
// start coding at ~18:50
// submission #1 at 19:24
// submission #2 at 19:49
accuracy: 1
time_ms: 10
memory_kb: 13748
final_rank: 18

code_snippet: #include<bits/stdc++.h>
#define rep(i, n) for(int i = 0; i < n; ++i)
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;

struct {
	int cn, hd[1000100], cur[1000100]; int dis[1000100];
	int ce, nxt[1000100], to[1000100]; int cap[1000100];
	void clr(int n){
		cn = n, ce = 0;
		fill(hd, hd+cn, -1);
	}
	void ae(int f, int t, int c){
		//cout << "ae " << f << " " << t << " " << c << endl;
		nxt[ce] = hd[f], to[ce] = t, cap[ce] = c, hd[f] = ce++;
		nxt[ce] = hd[t], to[ce] = f, cap[ce] = 0, hd[t] = ce++;
	}
	bool bfs(int S, int T){
		fill(dis, dis+cn, inf);
		dis[S] = 0;
		queue<int> q; q.emplace(S);
		while(!q.empty()){
			int u = q.front(); q.pop();
			for(int eid = hd[u]; eid >= 0; eid = nxt[eid]){
				int t = to[eid];
				if(cap[eid] && dis[t] > dis[u] + 1)
					dis[t] = dis[u] + 1, q.emplace(t);
			}
		}
		return dis[T] < inf;
	}
	int dfs(int u, int dest, int flow){
		if(u == dest) return flow;
		int nf = 0;
		for(int &eid = cur[u]; eid >= 0; eid = nxt[eid]){
			int t = to[eid];
			if(cap[eid] && dis[t] == dis[u] + 1){
				int ret = dfs(t, dest, min(cap[eid], flow-nf));
				nf += ret, cap[eid] -= ret, cap[eid^1] += ret;
				if(nf == flow)
					break;
			}
		}
		return nf;
	}
	int mf(int S, int T){
		int ret = 0;
		while(bfs(S, T)){
			rep(i, cn) cur[i] = hd[i];
			ret += dfs(S, T, inf);
		}
		return ret;
	}
} mf;

int n, m, a, b, c;
string s[44];
inline int id(int tp, int i, int j){ return 2 + tp*(n+1)*(m+1) + i*(m+1) + j; } // add 2+

int main(){
	ios::sync_with_stdio(false);

	cin >> n >> m >> a >> b >> c;
	mf.clr(2 + 4*(n+1)*(m+1));
	rep(i, n)
		cin >> s[i];

	for(int i = 1; i <= n; ++i) for(int j = 1; j <= m; ++j){
		//cout << "----------" << i << " " << j << "-------------" << endl;
		mf.ae(0, id(0, i, j), a);
		mf.ae(id(1, i, j), 1, a);
		if(s[i-1][j-1] == '#'){
			mf.ae(id(0, i, j), id(1, i, j), c);
		} else {
			mf.ae(id(1, i, j), id(0, i, j), inf); // add this
			mf.ae(0, id(2, i, j), a);
			mf.ae(id(3, i, j), 1, a);
			mf.ae(id(2, i, j), id(0, i, j), c);
			mf.ae(id(1, i, j), id(3, i, j), c);
		}
	}
	rep(i, n+1) rep(j, m+1) if(!i || !j){
		mf.ae(0, id(0, i, j), inf), mf.ae(id(3, i, j), 1, inf);
		mf.ae(id(1, i, j), 1, inf), mf.ae(0, id(2, i, j), inf);
	}

	rep(i, n+1) rep(j, m){
		mf.ae(id(0, i, j), id(0, i, j+1), b);
		mf.ae(id(3, i, j+1), id(3, i, j), b); // swap 2 3
	}
	rep(i, n) rep(j, m+1){
		mf.ae(id(1, i+1, j), id(1, i, j), b);
		mf.ae(id(2, i, j), id(2, i+1, j), b);
	}

	cout << mf.mf(0, 1) << "\n";

	//rep(i, mf.cn)
	//	if(mf.dis[i] < inf){
	//		cout << "to: " << (i-2) / (n*m) << " " << (i-2) % (n*m) / m << " " << (i-2) % (n*m) % m << endl;
	//	}

	return 0;
}

// by zxb
// start coding at ~18:50
// submission #1 at 19:24
accuracy: 0.07476635514018691
time_ms: 20
memory_kb: 13724
final_rank: 20

code_snippet: #include<bits/stdc++.h>
#define ll long long
#define gmax(x,y) x=max(x,y)
#define gmin(x,y) x=min(x,y)
#define F first
#define S second
#define P pair
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i<b;i++)
#define V vector
#define RE return
#define ALL(a) a.begin(),a.end()
#define MP make_pair
#define PB emplace_back
#define PF push_front
#define FILL(a,b) memset(a,b,sizeof(a))
#define lwb lower_bound
#define upb upper_bound
#define lc (x<<1)
#define rc ((x<<1)|1)
#define sz(x) ((int)x.size())
#define pc putchar
using namespace std;
int INF=1e9;
struct max_flow{
	struct node{int to,cap,rev;};
	node edge(int to1,int cap1,int rev1){
		node re;
		re.to=to1;
		re.cap=cap1;
		re.rev=rev1;
		RE re;
	}
	V<node> g[7005];
	int d[7005],cur[7005],vis[7005];
	void add(int u,int v,int cap){
		g[u].PB(edge(v,cap,g[v].size()));
		g[v].PB(edge(u,0,g[u].size()-1));
	} 
	void clear(int n){
		FOR(i,0,n)g[i].clear();
	}
	int q[7005];
	void bfs(int s){
		FILL(d,-1);
		d[s]=0;
		int st=1,ed=0;
		q[++ed]=s;
		int cur;
		while(st<=ed){
			cur=q[st++];
			for(auto &e:g[cur]){
				if(e.cap>0&&d[e.to]<0){
					d[e.to]=d[cur]+1;
					q[++ed]=e.to;
				}
			}
		}
	}
	int dfs(int v,int t,int f){
		int dist,re=0;
		if(v==t||!f)RE f;
		rep(i,cur[v],(int)g[v].size()){
			auto &e=g[v][i];
			if(e.cap>0&&d[v]<d[e.to]){
				dist=dfs(e.to,t,min(f,e.cap));
				if(dist>0){
					e.cap-=dist;
					g[e.to][e.rev].cap+=dist;
					re+=dist;
					f-=dist;
					if(!f)break;
				}
			}
			cur[v]++;
		}
		if(!re)d[v]=-1;
		RE re;
	}
	int get(int s,int t){
		int flow=0,f;
		while(1){
			bfs(s);
			if(d[t]<0)break;
			FILL(cur,0);
			f=dfs(s,t,INF);flow+=f;
		}
		FILL(vis,0);
		queue<int> q;
		q.emplace(s);
		vis[s]=1;
		while(!q.empty()){
			int now=q.front();q.pop();
			for(auto u:g[now])if(u.cap&&!vis[u.to]){
				vis[u.to]=1;
				q.emplace(u.to);
			}
		}
		RE flow;
	}
}mf;
int n,m,a,b,c;
char C[45][45];
int ithW[45][45],itlW[45][45],ithB[45][45],itlB[45][45];
int cnt=0;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m>>a>>b>>c;
	FOR(i,1,n)FOR(j,1,m)cin>>C[i][j];
	int S=0;
	FOR(i,1,n)FOR(j,1,m){
		ithW[i][j]=++cnt;itlW[i][j]=++cnt;
		ithB[i][j]=++cnt;itlB[i][j]=++cnt;
	}
	int T=++cnt;
	FOR(i,1,n)FOR(j,1,m){
		if(C[i][j]=='#'){
			mf.add(itlW[i][j],T,INF);
			mf.add(S,ithW[i][j],INF);
			mf.add(itlB[i][j],ithB[i][j],c);
		}else{
			mf.add(ithB[i][j],itlB[i][j],INF);
			mf.add(ithB[i][j],itlW[i][j],c);
			mf.add(ithW[i][j],itlB[i][j],c);
		}
	}
	FOR(i,1,m)mf.add(itlW[1][i],T,b),mf.add(S,itlB[1][i],b);
	FOR(i,1,n)mf.add(S,ithW[i][1],b),mf.add(ithB[i][1],T,b);
	FOR(i,2,n)FOR(j,1,m){
		mf.add(itlW[i][j],itlW[i-1][j],b);
		mf.add(itlB[i-1][j],itlB[i][j],b);
	}
	FOR(i,1,n)FOR(j,2,m){
		mf.add(ithW[i][j-1],ithW[i][j],b);
		mf.add(ithB[i][j],ithB[i][j-1],b);
	}
	FOR(i,1,n)FOR(j,1,m){
		mf.add(S,ithW[i][j],a);
		mf.add(ithB[i][j],T,a);
		mf.add(itlW[i][j],T,a);
		mf.add(S,itlB[i][j],a);
	}
	cout<<mf.get(S,T)<<'\n';
	RE 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4556
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,n) for(int i=1;i<=int(n);i++)
#define per(i,n) for(int i=int(n)-1;i>=0;i--)
#define per1(i,n) for(int i=int(n);i>0;i--)
#define all(c) c.begin(),c.end()
#define si(x) int(x.size())
#define pb push_back
#define eb emplace_back
#define fs first
#define sc second
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
template<class T,class U> bool chmax(T& x, U y){
	if(x<y){ x=y; return true; }
	return false;
}
template<class T,class U> bool chmin(T& x, U y){
	if(y<x){ x=y; return true; }
	return false;
}
template<class T> void mkuni(V<T>& v){sort(all(v));v.erase(unique(all(v)),v.end());}
template<class T> int lwb(const V<T>& v, const T& a){return lower_bound(all(v),a) - v.begin();}
template<class T>
V<T> Vec(size_t a) {
    return V<T>(a);
}
template<class T, class... Ts>
auto Vec(size_t a, Ts... ts) {
  return V<decltype(Vec<T>(ts...))>(a, Vec<T>(ts...));
}
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }

#ifdef LOCAL
#define show(x) cerr << "LINE" << __LINE__ << " : " << #x << " = " << (x) << endl
void dmpr(ostream& os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ~ ";
	dmpr(os,args...);
}
#define shows(...) cerr << "LINE" << __LINE__ << " : ";dmpr(cerr,##__VA_ARGS__)
#define dump(x) cerr << "LINE" << __LINE__ << " : " << #x << " = {";  \
	for(auto v: x) cerr << v << ","; cerr << "}" << endl;
#else
#define show(x) void(0)
#define dump(x) void(0)
#define shows(...) void(0)
#endif

template<class D> D divFloor(D a, D b){
	return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
template<class D> D divCeil(D a, D b) {
	return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}

template<class capType>
struct MaxFlow{
	using D = capType;
	const D inf = 1e9;
	struct edge{
		int to;
		D cap;
		int rev;
		edge(int to_,D cap_,int rev_):to(to_),cap(cap_),rev(rev_){}
	};

	int N;
	vector<vector<edge>> G;
	vector<int> level,iter;

	MaxFlow(int N_):N(N_){
		G = vector<vector<edge>>(N);
		level = vector<int>(N);
		iter = vector<int>(N);
	}

	void add_edge(int from, int to, D cap){
		edge e1(to,cap,(int)G[to].size());
		edge e2(from,0,(int)G[from].size());
		G[from].push_back(e1);
		G[to].push_back(e2);
	}
	void bfs(int s){
		level = vector<int>(N,-1);

		queue<int> que;
		level[s]=0;
		que.push(s);
		while(!que.empty()){
			int v=que.front();
			que.pop();
			for(int i=0;i<(int)G[v].size();i++){
				edge &e=G[v][i];
				if(e.cap>0 && level[e.to]<0){
					level[e.to]=level[v]+1;
					que.push(e.to);
				}
			}
		}
	}
	D dfs(int v,int t,D f){
		if(v==t) return f;
		for(int &i=iter[v];i<(int)G[v].size();i++){
			edge &e=G[v][i];
			if(e.cap>0 && level[v]<level[e.to]){
				D d = dfs(e.to,t,min(f,e.cap));
				if(d>0){
					e.cap-=d;
					G[e.to][e.rev].cap+=d;
					return d;
				}
			}
		}
		return 0;
	}
	D max_flow(int s,int t){
		D flow=0;
		while(true){
			bfs(s);
			if(level[t]<0) return flow;
			iter = vector<int>(N,0);
			D f;
			while( (f=dfs(s,t,inf))>0 ) flow+=f;
		}
	}

	vector<int> calcCut(int s,int t){
		vector<int> which(N,-1);			// 0: S, 1: T
		auto dfs2 = [&](auto& self, int v) -> void{
			if(which[v] != -1) return;
			which[v] = 0;
			for(auto e: G[v]) if(e.cap>0) self(self,e.to);
		};
		dfs2(dfs2,s);
		rep(i,N) if(which[i] == -1) which[i] = 1;
		assert(which[t] == 1);
		return which;
	}
};
struct UnionFind{
	vector<int> par;
	UnionFind(int N){
		par.assign(N,0);
		rep(i,N) par[i]=i;
	}
	int find(int x){
		if(par[x]==x) return x;
		return par[x]=find(par[x]);
	}
	bool same(int x,int y){
		return find(x)==find(y);
	}
	void unite(int x,int y){
		x=find(x),y=find(y);
		if(x==y) return;
		par[y]=x;
	}
};
template<class costType>
struct ProjectSelection{
	using D = costType;
	int N;
	vector<D> trueCost, falseCost;
	MaxFlow<D> MF;
	UnionFind UF;
	vector<bool> sol;

	ProjectSelection(int varnum):N(varnum), trueCost(N), falseCost(N), MF(N+2), UF(N+N), sol(N){
	}
	void addCost(int id, bool f, D cost){		// ok for cost < 0
		assert(0 <= id && id < N);
		(f ? trueCost : falseCost)[id] += cost;
	}
	struct Waf{
		int x;bool fx;int y;bool fy;D cost;
	};
	vector<Waf> memo;
	void addCost2(int x,bool fx, int y,bool fy, D cost){
		// x:fx  and  y:fy  =>  ans += cost
		assert(0 <= x && x < N); assert(0 <= y && y < N);
		if(fx == fy) UF.unite(x,y+N), UF.unite(y,x+N);
		else UF.unite(x,y), UF.unite(x+N,y+N);
		memo.push_back({x,fx,y,fy,cost});
	}
	D minCost(){
		bool isBipartite = true;
		rep(i,N) if(UF.same(i,i+N)) isBipartite = false;
		assert(isBipartite);
		V<int> which(N,-1);		// which[i] = 0 <=> i:true iff i: left(S) side <=> i:true iff cut off i->T
		rep(i,N){
			int r1 = UF.find(i), r2 = UF.find(i+N);
			which[i] = (r1 < r2 ? 0 : 1);
		}
		int S = N, T = N+1;
		D off = 0;
		rep(i,N){
			D mn = min(trueCost[i], falseCost[i]);
			trueCost[i] -= mn, falseCost[i] -= mn;
			off += mn;
			if(which[i] == 0){
				MF.add_edge(i,T,trueCost[i]);
				MF.add_edge(S,i,falseCost[i]);
			}else{
				MF.add_edge(i,T,falseCost[i]);
				MF.add_edge(S,i,trueCost[i]);
			}
		}
		for(auto e: memo){
			bool xisS = (e.fx ^ which[e.x]);
			bool yisS = (e.fy ^ which[e.y]);
			assert(xisS != yisS);
			if(xisS) MF.add_edge(e.x,e.y,e.cost);
			else MF.add_edge(e.y,e.x,e.cost);
		}
		D flow = MF.max_flow(S,T) + off;
		auto isT = MF.calcCut(S,T);
		rep(i,N) sol[i] = !(isT[i] ^ which[i]);
		return flow;
	}
};


int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);		//DON'T USE scanf/printf/puts !!
	cout << fixed << setprecision(20);

	int H,W,a,b,c; cin >> H >> W >> a >> b >> c;
	V<string> s(H); rep(i,H) cin >> s[i];

	ProjectSelection<int> PS(H*W*4);
	auto id = [&](int h,int w,int isblack,int isvert){
		return (h*W+w)*4 + isblack*2 + isvert;
	};
	const int inf = 1e9;
	rep(i,H) rep(j,W){
		rep(p,2) rep(q,2){
			PS.addCost(id(i,j,p,q),true,a);
		}
		rep(q,2) PS.addCost2(id(i,j,0,q),true,id(i,j,1,q),true, inf);
		rep(p,2){
			if(j != W-1){
				PS.addCost2(id(i,j,p,0),true, id(i,j+1,p,0),false, b);
			}else{
				PS.addCost(id(i,j,p,0),true, b);
			}
			if(i != H-1){
				PS.addCost2(id(i,j,p,1),true, id(i+1,j,p,1),false, b);
			}else{
				PS.addCost(id(i,j,p,1),true, b);
			}
		}
		if(s[i][j] == '#'){
			rep(q,2) PS.addCost(id(i,j,0,q),true, inf);
			PS.addCost2(id(i,j,1,0),false, id(i,j,1,1),false, c);
		}else{
			PS.addCost2(id(i,j,1,0),true, id(i,j,1,1),true, inf);
			PS.addCost2(id(i,j,1,0),true, id(i,j,0,1),false, c);
			PS.addCost2(id(i,j,1,1),true, id(i,j,0,0),false, c);
		}
	}
	cout << PS.minCost() << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 4632
final_rank: 17

code_snippet: #include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <numeric>
#include <queue>
#include <vector>
constexpr int kInf = 0x3f3f3f3f;
template <typename T>
void Read(T &x) {
  x = 0;
  int f = 1;
  char c;
  while ((c = std::getchar()) < '0' || c > '9')
    if (c == '-') f = -1;
  x = c - '0';
  while ((c = std::getchar()) >= '0' && c <= '9') x = x * 10 + (c - '0');
  x *= f;
}
template <typename T, typename... Args>
void Read(T &x, Args &... args) {
  Read(x);
  Read(args...);
}
template <typename T>
void checkmax(T &x, T y) {
  if (x < y) x = y;
}
template <typename T>
void checkmin(T &x, T y) {
  if (x > y) x = y;
}
struct Edge {
  int to, nxt, cost;
} e[200001];
int n, m, a, b, c, head[10001], E, bh[45][45], bv[45][45], wh[45][45],
    wv[45][45], tot, S, T, dep[10001], cur[10001];
char s[41][41];
void Add(int f, int t, int c) {
  e[E].to = t;
  e[E].cost = c;
  e[E].nxt = head[f];
  head[f] = E++;
}
bool Bfs() {
  std::queue<int> q;
  std::memset(dep, 0, sizeof(dep));
  dep[S] = 1;
  std::memcpy(cur, head, 4 * (tot + 1));
  q.emplace(S);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = head[u]; i != -1; i = e[i].nxt) {
      int v = e[i].to;
      if (e[i].cost && !dep[v]) {
        dep[v] = dep[u] + 1;
        q.emplace(v);
      }
    }
  }
  return dep[T];
}
int Dfs(int u, int sum) {
  if (u == T || !sum) return sum;
  int ans = 0;
  for (int i = cur[u]; i != -1; i = e[i].nxt) {
    int v = e[i].to;
    if (dep[v] == dep[u] + 1 && e[i].cost) {
      int min = Dfs(v, std::min(sum, e[i].cost));
      if (min) {
        e[i].cost -= min;
        e[i ^ 1].cost += min;
        ans += min;
        if (!(sum -= min)) break;
      }
    }
    cur[u] = e[i].nxt;
  }
  if (!ans) dep[u] = -1;
  return ans;
}
int Dinic() {
  int ans = 0;
  while (Bfs()) ans += Dfs(S, kInf);
  return ans;
}
int main(int argc, char const *argv[]) {
  std::memset(head, -1, sizeof(head));
  Read(n, m, a, b, c);
  for (int i = 1; i <= n; i++) std::scanf("%s", s[i] + 1);
  for (int i = 1; i <= n + 1; i++)
    for (int j = 1; j <= m + 1; j++) {
      bh[i][j] = ++tot;
      bv[i][j] = ++tot;
      wh[i][j] = ++tot;
      wv[i][j] = ++tot;
    }
  S = 0;
  T = ++tot;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      Add(S, bv[i][j], a), Add(bv[i][j], S, 0);
      Add(S, wh[i][j], a), Add(wh[i][j], S, 0);
      Add(bh[i][j], T, a), Add(T, bh[i][j], 0);
      Add(wv[i][j], T, a), Add(T, wh[i][j], 0);
      if (s[i][j] == '#') {
        Add(S, wh[i][j], kInf), Add(wh[i][j], S, 0);
        Add(wv[i][j], T, kInf), Add(T, wv[i][j], 0);
        Add(bv[i][j], bh[i][j], c), Add(bh[i][j], bv[i][j], 0);
      } else {
        Add(wh[i][j], bv[i][j], c), Add(bv[i][j], wh[i][j], 0);
        Add(bh[i][j], bv[i][j], kInf), Add(bv[i][j], bh[i][j], 0);
        Add(bh[i][j], wv[i][j], c), Add(wv[i][j], bh[i][j], 0);
      }
      Add(bv[i + 1][j], bv[i][j], b), Add(bv[i][j], bv[i + 1][j], 0);
      Add(wv[i][j], wv[i + 1][j], b), Add(wv[i + 1][j], wv[i][j], 0);
      Add(bh[i][j], bh[i][j + 1], b), Add(bh[i][j + 1], bh[i][j], 0);
      Add(wh[i][j + 1], wh[i][j], b), Add(wh[i][j], wh[i][j + 1], 0);
    }
  for (int i = 1; i <= n + 1; i++)
    for (int j = 1; j <= m + 1; j++)
      if (i > n || j > m) {
        Add(S, bv[i][j], kInf), Add(bv[i][j], S, 0);
        Add(S, wh[i][j], kInf), Add(wh[i][j], S, 0);
        Add(bh[i][j], T, kInf), Add(T, bh[i][j], 0);
        Add(wv[i][j], T, kInf), Add(T, wv[i][j], 0);
      }
  std::printf("%d\n", Dinic());
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4132
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using i64 = long long;
struct Flow {
    static constexpr int INF = 1e9;
    int n;
    struct Edge {
        int to, cap;
        Edge(int to, int cap) : to(to), cap(cap) {}
    };
    std::vector<Edge> e;
    std::vector<std::vector<int>> g;
    std::vector<int> cur, h;
    Flow(int n) : n(n), g(n) {}
    bool bfs(int s, int t) {
        h.assign(n, -1);
        std::queue<int> que;
        h[s] = 0;
        que.push(s);
        while (!que.empty()) {
            int u = que.front();
            que.pop();
            for (int i : g[u]) {
                int v = e[i].to;
                int c = e[i].cap;
                if (c > 0 && h[v] == -1) {
                    h[v] = h[u] + 1;
                    if (v == t)
                        return true;
                    que.push(v);
                }
            }
        }
        return false;
    }
    int dfs(int u, int t, int f) {
        if (u == t)
            return f;
        int r = f;
        for (int &i = cur[u]; i < int(g[u].size()); ++i) {
            int j = g[u][i];
            int v = e[j].to;
            int c = e[j].cap;
            if (c > 0 && h[v] == h[u] + 1) {
                int a = dfs(v, t, std::min(r, c));
                e[j].cap -= a;
                e[j ^ 1].cap += a;
                r -= a;
                if (r == 0)
                    return f;
            }
        }
        return f - r;
    }
    void addEdge(int u, int v, int c) {
        g[u].push_back(e.size());
        e.emplace_back(v, c);
        g[v].push_back(e.size());
        e.emplace_back(u, 0);
    }
    int maxFlow(int s, int t) {
        int ans = 0;
        while (bfs(s, t)) {
            cur.assign(n, 0);
            ans += dfs(s, t, INF);
        }
        return ans;
    }
};

constexpr int inf = 1E9;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int n, m, a, b, c;
    std::cin >> n >> m >> a >> b >> c;
    
    std::string s[n];
    for (int i = 0; i < n; i++) {
        std::cin >> s[i];
    }
    
    const int N = n * m;
    
    const int source = 4 * N;
    const int sink = 4 * N + 1;
    
    Flow g(4 * N + 2);
    
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int u = i * m + j;
            g.addEdge(u, sink, a);
            g.addEdge(source, 2 * N + u, a);
            if (i > 0) {
                g.addEdge(u, u - m, b);
            } else {
                g.addEdge(u, sink, b);
            }
            if (j > 0) {
                g.addEdge(2 * N + u - 1, 2 * N + u, b);
            } else {
                g.addEdge(source, 2 * N + u, b);
            }
            if (s[i][j] == '#') {
                g.addEdge(source, N + u, inf);
                g.addEdge(3 * N + u, sink, inf);
                g.addEdge(2 * N + u, u, c);
            } else {
                g.addEdge(source, N + u, a);
                g.addEdge(3 * N + u, sink, a);
                if (i > 0) {
                    g.addEdge(N + u - m, N + u, b);
                } else {
                    g.addEdge(source, N + u, b);
                }
                if (j > 0) {
                    g.addEdge(3 * N + u, 3 * N + u - 1, b);
                } else {
                    g.addEdge(3 * N + u, sink, b);
                }
                g.addEdge(u, 2 * N + u, inf);
                g.addEdge(u, 3 * N + u, c);
                g.addEdge(N + u, 2 * N + u, c);
            }
        }
    }
    
    std::cout << g.maxFlow(source, sink) << "\n";
    
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4148
final_rank: 4

code_snippet: /*
after dusk passed,
there is a starry sky.
*/
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define m_k make_pair
#define len(a) (int)a.size()
using namespace std;
const int N=2*1e5+100,M=45;
int n,m,A,B,C,s,t,d[N],nrl[N],cnt,bh[M][M],bv[M][M],wh[M][M],wv[M][M];
int tot,first[N],nxt[N*2],point[N*2],data[N*2];
char ch[M][M];
vector <int> u,v,w;
inline int read()
{
	int f=1,x=0;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
	return x*f;
}
inline void add_edge(int x,int y,int z)
{
	u.push_back(x);v.push_back(y);w.push_back(z);
	nxt[++tot]=first[x],first[x]=tot;
	point[tot]=y,data[tot]=z;
	nxt[++tot]=first[y],first[y]=tot;
	point[tot]=x,data[tot]=0;
}
bool bfs(int s,int t)
{
	queue <int> q;
	for (int i=1;i<=cnt;i++) d[i]=inf,nrl[i]=first[i];
	q.push(s);d[s]=0;
	while (!q.empty())
	{
		int x=q.front();q.pop();
		for (int i=first[x];i!=-1;i=nxt[i])
		{
			int u=point[i];
			if (d[u]>d[x]+1&&data[i])
			{
				d[u]=d[x]+1;
				if (u==t) return 1;
				q.push(u);
			}
		}
	}
	return 0;
}
int dfs(int x,int flow)
{
	if (x==t) return flow;
	int sum=0;
	for (int i=nrl[x];i!=-1;i=nxt[i])
	{
		int u=point[i];
		if (d[u]==d[x]+1&&data[i])
		{
			int tmp=dfs(u,min(flow,data[i]));
			flow-=tmp;data[i]-=tmp;
			sum+=tmp;data[i^1]+=tmp;
			if (flow<=0) break;
		}
		nrl[x]=nxt[i];
	}
	return sum;
}
signed main()
{
	tot=-1;
	memset(first,-1,sizeof(first));
	n=read();m=read();A=read();B=read();C=read();
	for (int i=1;i<=n;i++) scanf("%s",ch[i]+1);
	s=++cnt;t=++cnt;
	for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
	{
		bh[i][j]=++cnt;bv[i][j]=++cnt;
		wh[i][j]=++cnt;wv[i][j]=++cnt;
	}
	for (int j=1;j<=m;j++)
	{
		bh[n+1][j]=++cnt,wh[n+1][j]=++cnt;
		add_edge(s,bh[n+1][j],inf);
		add_edge(wh[n+1][j],t,inf);
	}
	for (int i=1;i<=n;i++)
	{
		bv[i][m+1]=++cnt,wv[i][m+1]=++cnt;
		add_edge(bv[i][m+1],t,inf);
		add_edge(s,wv[i][m+1],inf);
	}
	for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
	{
		if (ch[i][j]=='#')
		{
			add_edge(s,bh[i][j],A);
			add_edge(bh[i][j],bv[i][j],C);
			add_edge(bv[i][j],t,A);
			add_edge(s,wv[i][j],inf);
			add_edge(wh[i][j],t,inf);
		}
		else
		{
			add_edge(s,bh[i][j],A);
			add_edge(s,wv[i][j],A);
			add_edge(wv[i][j],bh[i][j],C);
			add_edge(bv[i][j],t,A);
			add_edge(wh[i][j],t,A);
			add_edge(bv[i][j],wh[i][j],C);
			add_edge(bv[i][j],bh[i][j],inf);
		}
	}
	for (int i=1;i<=n;i++) for (int j=1;j<=m;j++)
	{
		add_edge(bh[i+1][j],bh[i][j],B);
		add_edge(bv[i][j],bv[i][j+1],B);
		add_edge(wh[i][j],wh[i+1][j],B);
		add_edge(wv[i][j+1],wv[i][j],B);
	}
	// printf("%d %d %d %d\n",cnt,len(u),s,t);
	// for (int i=0;i<len(u);i++) printf("%d %d %d\n",u[i],v[i],w[i]);
	int ans=0;
	while (bfs(s,t)) ans+=dfs(s,inf);
	printf("%d\n",ans);
}
accuracy: 1
time_ms: 10
memory_kb: 4696
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 40 + 5;
const int MAXM = 40 + 5;
const int MAXP = MAXN * MAXM;
const int inf = 0x3f3f3f3f;

template<const int MAXN,const int MAXM>
struct Max_Flow
{
	struct Edge
	{
		int next,to,flow;
	}e[MAXM<<1];
	int head[MAXN], etot;
	inline void add_one(int u,int v,int flow)
	{
		e[++etot] = (Edge){ head[u],v,flow};
		head[u] = etot;
	}
	inline void add_edge(int u,int v,int flow){ add_one(u,v,flow); add_one(v,u,0);}
	
	int n,s,t;
	int dep[MAXN], cur[MAXN];
	inline void clear(void){ etot=-1; memset(head,-1,sizeof(head));}
	inline void init(int _n,int _s,int _t){ n = _n; s = _s; t = _t;}
	inline bool bfs(void)
	{
		for(int i=1; i<=n; ++i) dep[i] = -1, cur[i] = head[i];
		queue<int> q;
		dep[s] = 0; q.push(s);
		while(q.size())
		{
			int u = q.front(); q.pop();
			for(int i=head[u]; ~i; i=e[i].next) if(e[i].flow)
			{
				int v = e[i].to;
				if(dep[v] == -1) dep[v] = dep[u] + 1, q.push(v);
			}
		}
		return ~dep[t];
	}
	int dfs(int u,int maxf)
	{
		if(u == t || !maxf) return maxf;
		int res=0;
		for(int &i=cur[u], f; ~i; i=e[i].next)
			if(e[i].flow && dep[e[i].to] == dep[u] + 1 && (f = dfs(e[i].to, min(e[i].flow, maxf))))
			{
				e[i].flow -= f; e[i^1].flow += f;
				res += f; maxf -= f;
				if(!maxf) return res;
			}
		return res;
	}
	inline int dinic(void)
	{
		int res=0;
		while(bfs()) res += dfs(s,inf);
		return res;
	}
};

Max_Flow<MAXP * 4, MAXP * 13> mf;

int n,m;
char s[MAXN][MAXM];
int pid[MAXN][MAXM][5];

void solve(void)
{
	int a,b,c;
	scanf("%d%d%d%d%d",&n,&m,&a,&b,&c);
	for(int i=1; i<=n; ++i) scanf("%s",s[i]+1);
	
	int pcnt = 0;
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j)
			for(int k=1; k<=4; ++k)
				pid[i][j][k] = ++pcnt;
	int S = ++pcnt, T = ++pcnt;
	
	mf.clear();
	mf.init(pcnt, S, T);
	
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j)
		{
			int p1 = pid[i][j][1], p2 = pid[i][j][2], p3 = pid[i][j][3], p4 = pid[i][j][4];
			mf.add_edge(S, p1, a);
			mf.add_edge(S, p4, s[i][j] == '.'? a: inf);
			mf.add_edge(p3, T, s[i][j] == '.'? a: inf);
			mf.add_edge(p2, T, a);
			
			mf.add_edge(p3, p1, inf);
			mf.add_edge(p2, p4, inf);
			
			if(s[i][j] == '#')
				mf.add_edge(p1, p2, c);
			else
			{
				mf.add_edge(p2, p1, inf);
				mf.add_edge(p4, p1, c);
				mf.add_edge(p2, p3, c);
			}
			
			if(i == n)
				mf.add_edge(S, p1, b),
				mf.add_edge(p3, T, b);
			else
				mf.add_edge(pid[i+1][j][1], p1, b),
				mf.add_edge(p3, pid[i+1][j][3], b);
			
			if(j == m)
				mf.add_edge(p2, T, b),
				mf.add_edge(S, p4, b);
			else
				mf.add_edge(p2, pid[i][j+1][2], b),
				mf.add_edge(pid[i][j+1][4], p4, b);
		}
	
	printf("%d\n",mf.dinic());
}

int main(void)
{
	int T = 1;
	while(T--) solve();
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3908
final_rank: 16

code_snippet: #include <bits/stdc++.h>

#define fi first
#define se second
#define DB double
#define U unsigned
#define P std::pair
#define LL long long
#define LD long double
#define pb emplace_back
#define MP std::make_pair
#define SZ(x) ((int)x.size())
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 1e5 + 5;

struct Edge{
	int to,w,nxt;
}e[MAXN<<1];
int head[MAXN],cur[MAXN],dep[MAXN],cnt=1;
int S,T,N;

inline void add(int u,int v,int w){
	e[++cnt] = (Edge){v,w,head[u]};head[u] = cnt;
	e[++cnt] = (Edge){u,0,head[v]};head[v] = cnt;
}

inline bool bfs(){
	FOR(i,1,N) cur[i] = head[i],dep[i] = 0;
	std::queue<int> q;q.push(S);dep[S] = 1;
	while(!q.empty()){
		int v = q.front();q.pop();
		for(int i = head[v];i;i = e[i].nxt){
			if(e[i].w > 0 && !dep[e[i].to]){
				dep[e[i].to] = dep[v] + 1;
				q.push(e[i].to);
			}
		}
	}
	return dep[T];
}

inline int dfs(int v,int lim=1e9){
	if(!lim) return 0;
	if(v == T) return lim;
	int res = 0;
	for(int &i = cur[v];i;i = e[i].nxt){
		if(e[i].w > 0 && dep[e[i].to] == dep[v] + 1){
			int w = dfs(e[i].to,std::min(lim,e[i].w));
			if(w){
				e[i].w -= w;e[i^1].w += w;
				res += w;lim -= w;
				if(!lim) break;
			}
		}
	}
	return res;
}

inline int Dinic(){
	int res = 0,t = 0;
	while(bfs()) while((t=dfs(S))) res += t;
	return res;
}

int n,m,A,B,C;
char str[55][55];

int bh[55][55],bv[55][55],wh[55][55],wv[55][55];

inline void Solve(){
	scanf("%d%d%d%d%d",&n,&m,&A,&B,&C);
	FOR(i,1,n) scanf("%s",str[i]+1);
	S = 1;N = T = 2;
	FOR(i,1,n) FOR(j,1,m){
		bh[i][j] = ++N;
		bv[i][j] = ++N;
		wh[i][j] = ++N;
		wv[i][j] = ++N;
	}
	FOR(i,1,n) FOR(j,1,m){
		if(i == 1){
			add(wv[i][j],T,B);
			add(S,bv[i][j],B);
		}
		else{
			add(wv[i][j],wv[i-1][j],B);
			add(bv[i-1][j],bv[i][j],B);
		}
		if(j == 1){
			add(S,wh[i][j],B);
			add(bh[i][j],T,B);
		}
		else{
			add(wh[i][j-1],wh[i][j],B);
			add(bh[i][j],bh[i][j-1],B);
		}
		if(str[i][j] == '#'){
			add(S,wh[i][j],1e9);
			add(wv[i][j],T,1e9);
			add(S,bv[i][j],A);
			add(bh[i][j],T,A);
			add(bv[i][j],bh[i][j],C);
		}
		else{
			add(S,wh[i][j],A);
			add(wv[i][j],T,A);
			add(S,bv[i][j],A);
			add(bh[i][j],T,A);

			add(bh[i][j],bv[i][j],1e9);

			add(bh[i][j],wv[i][j],C);
			add(wh[i][j],bv[i][j],C);
		}
	}
	printf("%d\n",Dinic());
	FOR(i,1,N) head[i] = 0;cnt = 1;
}

int main(){
	//freopen("draw.in","r",stdin);
	//freopen("draw.out","w",stdout);
	//int T;scanf("%d",&T);
	int T = 1;
	while(T--) Solve();
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3804
final_rank: 2

code_snippet: #include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
#define N 42
#define M 6406
int n,m,a,b,c,ct,head[M],cnt=1,dis[M],cur[M];
char s[N][N];
struct edge{int t,next,v;}ed[M*20];
void adde(int f,int t,int v){ed[++cnt]=(edge){t,head[f],v};head[f]=cnt;ed[++cnt]=(edge){f,head[t],0};head[t]=cnt;}
bool bfs(int s,int t)
{
	for(int i=1;i<=ct;i++)cur[i]=head[i],dis[i]=-1;
	queue<int> qu;
	qu.push(s);dis[s]=0;
	while(!qu.empty())
	{
		int u=qu.front();qu.pop();
		for(int i=head[u];i;i=ed[i].next)if(ed[i].v&&dis[ed[i].t]==-1)
		{
			dis[ed[i].t]=dis[u]+1;qu.push(ed[i].t);
			if(ed[i].t==t)return 1;
		}
	}
	return 0;
}
int dfs(int u,int t,int f)
{
	if(u==t||!f)return f;
	int as=0,tp;
	for(int &i=cur[u];i;i=ed[i].next)if(ed[i].v&&dis[ed[i].t]==dis[u]+1&&(tp=dfs(ed[i].t,t,min(f,ed[i].v))))
	{
		ed[i].v-=tp;ed[i^1].v+=tp;
		as+=tp;f-=tp;
		if(!f)return as;
	}
	return as;
}
int dinic(){int ls=1e9,as=0;while(ls&&bfs(ct-1,ct)){int tp=dfs(ct-1,ct,ls);ls-=tp;as+=tp;}return as;}
int getid(int x,int y,int t1,int t2){return (x-1)*m+y+(t1*2+t2)*n*m;}
int main()
{
	scanf("%d%d%d%d%d",&n,&m,&a,&b,&c);
	for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
	ct=n*m*4+2;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	{
		if(i>1)adde(getid(i,j,0,0),getid(i-1,j,0,0),b),adde(getid(i-1,j,1,0),getid(i,j,1,0),b);
		else adde(getid(i,j,0,0),ct,b),adde(ct-1,getid(i,j,1,0),b);
		if(j>1)adde(getid(i,j,1,1),getid(i,j-1,1,1),b),adde(getid(i,j-1,0,1),getid(i,j,0,1),b);
		else adde(getid(i,j,1,1),ct,b),adde(ct-1,getid(i,j,0,1),b);
		for(int p=0;p<2;p++)for(int q=0;q<2;q++)if((p+q)&1)adde(ct-1,getid(i,j,p,q),a);else adde(getid(i,j,p,q),ct,a);
		if(s[i][j]=='#')adde(getid(i,j,0,1),getid(i,j,0,0),c),adde(ct-1,getid(i,j,1,0),1e9),adde(getid(i,j,1,1),ct,1e9);
		else adde(getid(i,j,0,0),getid(i,j,0,1),1e9),adde(getid(i,j,0,0),getid(i,j,1,0),1e9),adde(getid(i,j,0,0),getid(i,j,1,1),c),
		adde(getid(i,j,1,1),getid(i,j,0,1),1e9),adde(getid(i,j,1,0),getid(i,j,0,1),c);
	}
	printf("%d\n",dinic());
}
/*
consider 4 points:
1b,2b,1w,2w
cost:a
if (x,y) is 1b and (x-1,y) isn't 1b cost b
if (x,y) is 2b and (x,y-1) isn't 2b cost b
if (x,y) is 1w and (x-1,y) isn't 1w cost b
if (x,y) is 2w and (x,y-1) isn't 2w cost b
for a black point if (x,y) isn't 1b and (x,y) isn't 2b cost c
for a black point if (x,y) is 1w or 2w cost 10^114
for a white point if (x,y) is 1b and (x,y) is 2b cost 10^114
for a white point if (x,y) is 1b and is 1w cost 10^114
for a white point if (x,y) is 1b and isn't 2w cost c
for a white point if (x,y) is 2b and is 2w cost 10^114
for a white point if (x,y) is 2b and isn't 1w cost c
flip 2b,1w
*/
accuracy: 1
time_ms: 10
memory_kb: 3376
final_rank: 1

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 6505
#define SIZE 45

enum Type{
	BH,
	neg_BV,
	neg_WH,
	WV,
};

struct Edge{
	Edge(int arg_to,int arg_capacity,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		rev_index = arg_rev_index;
	}
	int to,capacity,rev_index;
};

int V,E;

vector<Edge> G[NUM];
int dist[NUM];
int cheked_index[NUM];
int INDEX[4][SIZE][SIZE];
char table[SIZE][SIZE];


void add_edge(int from,int to,int capacity){
	G[from].push_back(Edge(to,capacity,G[to].size()));
	G[to].push_back(Edge(from,0,G[from].size()-1));
}


void bfs(int source){
	for(int i = 0; i < V; i++)dist[i] = -1;
	queue<int> Q;
	dist[source] = 0;
	Q.push(source);

	while(!Q.empty()){
		int node_id = Q.front();
		Q.pop();
		for(int i = 0; i < G[node_id].size(); i++){
			Edge &e = G[node_id][i];
			if(e.capacity > 0 && dist[e.to] < 0){
				dist[e.to] = dist[node_id]+1;
				Q.push(e.to);
			}
		}
	}
}

int dfs(int node_id,int sink,int flow){
	if(node_id == sink)return flow;

	for(int &i = cheked_index[node_id]; i < G[node_id].size(); i++){
		Edge &e = G[node_id][i];
		if(e.capacity > 0 && dist[node_id] < dist[e.to]){
			int tmp_flow = dfs(e.to,sink,min(flow,e.capacity));
			if(tmp_flow > 0){
				e.capacity -= tmp_flow;
				G[e.to][e.rev_index].capacity += tmp_flow;
				return tmp_flow;
			}
		}
	}
	return 0;
}


int max_flow(int source,int sink){
	int flow = 0,add;
	while(true){
		bfs(source);
		if(dist[sink] < 0)break;
		for(int i = 0; i < V; i++)cheked_index[i] = 0;
		while((add = dfs(source,sink,BIG_NUM)) > 0){
			flow += add;
		}
	}
	return flow;
}


int main(){

	int H,W,A,B,C;
	scanf("%d %d %d %d %d",&H,&W,&A,&B,&C);

	for(int row = 0; row < H; row++){

		scanf("%s",table[row]);
	}

	int source = 0,sink = 1;
	int index = 2;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			for(int i = 0; i < 4; i++){

				INDEX[i][row][col] = index++;
			}
		}
	}

	V = index;

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			add_edge(source,INDEX[BH][row][col],A);
			add_edge(source,INDEX[WV][row][col],A);

			add_edge(INDEX[neg_BV][row][col],sink,A);
			add_edge(INDEX[neg_WH][row][col],sink,A);

			if(col < W-1){

				add_edge(INDEX[BH][row][col+1],INDEX[BH][row][col],B);
				add_edge(INDEX[neg_WH][row][col],INDEX[neg_WH][row][col+1],B);

			}else{

				add_edge(source,INDEX[BH][row][col],B);
				add_edge(INDEX[neg_WH][row][col],sink,B);
			}

			if(row < H-1){

				add_edge(INDEX[neg_BV][row][col],INDEX[neg_BV][row+1][col],B);
				add_edge(INDEX[WV][row+1][col],INDEX[WV][row][col],B);

			}else{

				add_edge(source,INDEX[WV][row][col],B);
				add_edge(INDEX[neg_BV][row][col],sink,B);
			}
		}
	}

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){

			if(table[row][col] == '#'){

				add_edge(source,INDEX[WV][row][col],BIG_NUM);
				add_edge(INDEX[neg_WH][row][col],sink,BIG_NUM);
				add_edge(INDEX[BH][row][col],INDEX[neg_BV][row][col],C);

			}else{ //table[row][col] == '.'

				add_edge(INDEX[WV][row][col],INDEX[BH][row][col],C);
				add_edge(INDEX[neg_BV][row][col],INDEX[neg_WH][row][col],C);
				add_edge(INDEX[neg_BV][row][col],INDEX[BH][row][col],BIG_NUM);
			}
		}
	}

	printf("%d\n",max_flow(source,sink));

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3900
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define loop(i, a) for (int i = 0; i < (a); ++i)
#define cont(i, a) for (int i = 1; i <= (a); ++i)
#define circ(i, a, b) for (int i = (a); i <= (b); ++i)
#define range(i, a, b, c) for (int i = (a); (c) > 0 ? i <= (b) : i >= (b); i += (c))
#define parse(it, x) for (auto &it : (x))
#define pub push_back
#define pob pop_back
#define emb emplace_back
#define mak make_pair
#define mkt make_tuple
typedef long long ll;
typedef long double lf;
const int Inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;

struct Edge {
	int to, cap, rev;
	Edge(int to, int cap, int rev): to(to), cap(cap), rev(rev) {}
};

struct NetFlow {
	vector<Edge> egs[10005];
	void inline addedge(int u, int v, int cap) {
		egs[u].emb(v, cap, SZ(egs[v]));
		egs[v].emb(u, 0, SZ(egs[u]) - 1);
	}
	int dist[10005];
	bool inline bfs(int s, int t) {
		memset(dist, -1, sizeof(dist));
		dist[s] = 0;
		queue<int> q; q.push(s);
		while (SZ(q)) {
			int x = q.front(); q.pop();
			parse(e, egs[x]) {
				if (e.cap && !~dist[e.to]) {
					dist[e.to] = dist[x] + 1;
					q.push(e.to);
				}
			}
		}
		return ~dist[t];
	}
	int iter[10005];
	int inline dfs(int x, int t, int cap) {
		if (x == t) return cap;
		for (int &i = iter[x]; i < SZ(egs[x]); ++i) {
			Edge &e = egs[x][i];
			if (e.cap && dist[e.to] == dist[x] + 1) {
				int f = dfs(e.to, t, min(cap, e.cap));
				if (f) {
					e.cap -= f;
					egs[e.to][e.rev].cap += f;
					return f;
				}
			}
		}
		return 0;
	}
	int inline get(int s, int t) {
		int res = 0;
		while (bfs(s, t)) {
			memset(iter, 0, sizeof(iter));
			for (int tmp; (tmp = dfs(s, t, Inf)); res += tmp) ;
		}
		return res;
	}
} nf;

int n, m, a, b, c;
char s[55][55];

int id(int i, int j, int k) {
	return (i * (m + 1) + j) * 4 + k + 1;
}

int main() {
	scanf("%d%d%d%d%d", &n, &m, &a, &b, &c);
	loop(i, n) scanf("%s", s[i]);
	int S = 0, T = 10004;
	loop(i, n) loop(j, m) {
		nf.addedge(id(i, j, 0), T, a);
		nf.addedge(id(i, j, 0), id(i, j + 1, 0), b);
		nf.addedge(S, id(i, j, 1), a);
		nf.addedge(id(i + 1, j, 1), id(i, j, 1), b);
		nf.addedge(S, id(i, j, 2), a);
		nf.addedge(id(i, j + 1, 2), id(i, j, 2), b);
		nf.addedge(id(i, j, 3), T, a);
		nf.addedge(id(i, j, 3), id(i + 1, j, 3), b);
	}
	loop(i, n + 1) loop(j, m + 1) {
		if (i < n && j < m) {
			if (s[i][j] == '#') {
				nf.addedge(id(i, j, 1), id(i, j, 0), c);
				nf.addedge(S, id(i, j, 2), Inf);
				nf.addedge(id(i, j, 3), T, Inf);
			} else {
				nf.addedge(id(i, j, 0), id(i, j, 1), Inf);
				nf.addedge(id(i, j, 0), id(i, j, 3), c);
				nf.addedge(id(i, j, 2), id(i, j, 1), c);
			}
		} else {
			nf.addedge(id(i, j, 0), T, Inf);
			nf.addedge(S, id(i, j, 1), Inf);
			nf.addedge(S, id(i, j, 2), Inf);
			nf.addedge(id(i, j, 3), T, Inf);
		}
	}
	printf("%d\n", nf.get(S, T));
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4580
final_rank: 9