Problem:
Score : 600 points

Problem Statement

There is a board with N rows and M columns.
The information of this board is represented by N strings S_1,S_2,\ldots,S_N.
Specifically, the state of the square at the i-th row from the top and the j-th column from the left is represented as follows:

S_{i,j}=. : the square is empty.

S_{i,j}=# : an obstacle is placed on the square.

S_{i,j}=o : a piece is placed on the square.

Yosupo repeats the following operation:

Choose a piece and move it to its right adjecent square or its down adjacent square.
Moving a piece to squares with another piece or an obstacle is prohibited.
Moving a piece out of the board is also prohibited.

Yosupo wants to perform the operation as many times as possible.
Find the maximum possible number of operations.

Constraints

1 \leq N \leq 50

1 \leq M \leq 50

S_i is a string of length M consisting of ., # and o.

1 \leq ( the number of pieces )\leq 100.
In other words, the number of pairs (i, j) that satisfy S_{i,j}=o is between 1 and 100, both inclusive.

Input

Input is given from Standard Input in the following format:

N M
S_1
S_2
\vdots
S_N

Output

Print the maximum possible number of operations in a line.

Sample Input 1

3 3
o..
...
o.#

Sample Output 1

4

Yosupo can perform operations 4 times as follows:

o.. .o. ..o ... ...
... -> ... -> ... -> ..o -> ..o
o.# o.# o.# o.# .o#

Sample Input 2

9 10
.#....o#..
.#..#..##o
.....#o.##
.###.#o..o
#.#...##.#
..#..#.###
#o.....#..
....###..o
o.......o#

Sample Output 2

24

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using static System.Math;
using System.Numerics;
using System.Threading;
using System.Runtime.CompilerServices;
using nint=System.Int32;
static class Program{
	const int mod=(int)1e9+7;
	static readonly int[][] di1=new int[][]{new int[]{-1,0},new int[]{1,0},new int[]{0,-1},new int[]{0,1}};
	static readonly int[][] di2=new int[][]{new int[]{-1,-1},new int[]{-1,0},new int[]{-1,1},new int[]{0,-1},new int[]{0,1},new int[]{1,-1},new int[]{1,0},new int[]{1,1}};
	static char[][] bm;
	static void Main(){
		Sc sc=new Sc();
		var s=sc.Ia;
		int h=s[0],w=s[1];
		char c='#';
		bm=new char[h+2][];
		for(int i = 1;i<=h;i++) {bm[i]=(c+sc.S+c).ToCharArray();}
		bm[0]=bm[h+1]=new string(c,w+2).ToCharArray();
		var fl=new Mcfp(s[0]*s[1]+2,s[0]*(s[1]-1)+s[1]*(s[0]-1)+s[0]*s[1]*2);
		int o=0;
		for(int i = 1;i<=h;i++) {
			for(int j = 1;j<=w;j++) {
				if(bm[i][j]==c){continue;}
				if(bm[i][j]=='o'){
					fl.Edge(s[0]*s[1],j-1+(i-1)*s[1],1,0);
					o++;
				}
				fl.Edge(j-1+(i-1)*s[1],s[0]*s[1]+1,1,0);
				if(bm[i][j+1]!=c){fl.Edge(j-1+(i-1)*s[1],j+(i-1)*s[1],s[0]*s[1],-1);}
				if(bm[i+1][j]!=c){fl.Edge(j-1+(i-1)*s[1],j-1+i*s[1],s[0]*s[1],-1);}
			}
		}
		Console.WriteLine(-fl.Pd2(s[0]*s[1],s[0]*s[1]+1,o));
	}
	static void Fdi(int y,int x,Action<int,int> f){for(int i=0;i<4;i++){f(y+di1[i][0],x+di1[i][1]);}}
}
public class Mcfp{
	private List<int>[] li;
	private Eg[] h;
	private nint[][] pt;
	private int[] l,r;
	private nint[] z,u;
	private bool[] b1,b2;
	private int n,p=0;
	private const nint inf=nint.MaxValue;
	public class Eg{
		public int n;
		public nint e,c;
		public Eg(int n,nint e,nint c){this.n=n;this.e=e;this.c=c;}
	}
	public Mcfp(int n,int m){
		this.n=n;
		m<<=1;
		li=new List<int>[n];
		z=new nint[n];
		l=new int[n];
		r=new int[n];
		u=new nint[n];
		h=new Eg[m];
		for(int i=0;i<n;i++){
			li[i]=new List<int>();
			z[i]=u[i]=inf;
		}
	}
	public void Edge(int a,int b,int e,nint c){
		if(a==b){return;}
		li[a].Add(p);
		li[b].Add(p+1);
		h[p]=new Eg(b,e,c);
		h[p+1]=new Eg(a,0,-c);
		p+=2;
	}
	public long Pd1(int s,int t,int c){
		long ans=0,d=0;
		pt=new nint[][]{new nint[n],new nint[n]};
		int k=0;
		while(c>d){
			b1=new bool[n];
			b2=new bool[n];
			var pq=new Rheap<int>(32);
			z[s]=0;
			l[s]=-1;
			b2[s]=true;
			pq.Push(new Rheap<int>.Dt(0,s));
			bool bo=false;
			while(pq.cnt>0){
				var e=pq.Dequeue;
				if(b1[e.d]){continue;}
				b1[e.d]=true;
				if(e.d==t){bo=true;}
				for(int i=0;i<li[e.d].Count;i++){
					if(h[li[e.d][i]].e==0){continue;}
					nint co=e.n+h[li[e.d][i]].c-pt[k^1][h[li[e.d][i]].n]+pt[k^1][e.d];
					if(!b2[h[li[e.d][i]].n]||z[h[li[e.d][i]].n]>co){
						b2[h[li[e.d][i]].n]=true;
						z[h[li[e.d][i]].n]=co;
						pt[k][h[li[e.d][i]].n]=pt[k^1][h[li[e.d][i]].n]+co;
						l[h[li[e.d][i]].n]=e.d;
						r[h[li[e.d][i]].n]=li[e.d][i];
						u[h[li[e.d][i]].n]=Min(u[e.d],h[li[e.d][i]].e);
						pq.Push(new Rheap<int>.Dt(z[h[li[e.d][i]].n],h[li[e.d][i]].n));
					}
					else if(z[h[li[e.d][i]].n]==co){
						var o=Min(u[e.d],h[li[e.d][i]].e);
						if(u[h[li[e.d][i]].n]<o){
							u[h[li[e.d][i]].n]=o;
							l[h[li[e.d][i]].n]=e.d;
							r[h[li[e.d][i]].n]=li[e.d][i];
						}
					}
				}
			}
			if(!bo){break;}
			u[t]=(int)Min(c-d,u[t]);
			for(int i = t;i!=s;i=l[i]) {
				ans+=u[t]*h[r[i]].c;
				h[r[i]].e-=u[t];
				h[r[i]^1].e+=u[t];
			}
			k^=1;
			d+=u[t];
		}
		return c==d?ans:-1;
	}
	public long Pd2(int s,int t,int c){
		long ans=0,d=0;
		z[s]=0;
		l[s]=-1;
		b1=new bool[n];
		pt=new nint[][]{new nint[n],new nint[n]};
		int m=p;
		bool bo=true;
		for(int i=0;bo&&i<n;i++){
			bo=false;
			for(int j=0;j<m;j++){
				if(h[j].e!=0&&z[h[j^1].n]!=inf&&z[h[j].n]>z[h[j^1].n]+h[j].c){
					z[h[j].n]=z[h[j^1].n]+h[j].c;
					pt[0][h[j].n]=z[h[j].n];
					l[h[j].n]=h[j^1].n;
					r[h[j].n]=j;
					u[h[j].n]=Min(u[h[j^1].n],h[j].e);
					bo=true;
					if(i==n){b1[h[j].n]=true;}
				}
			}
		}
		u[t]=(int)Min(c-d,u[t]);
		for(int i = t;i!=s;i=l[i]) {
			ans+=u[t]*h[r[i]].c;
			h[r[i]].e-=u[t];
			h[r[i]^1].e+=u[t];
		}
		d+=u[t];
		int k=1;
		if(c==d){return ans;}
		while(c>d){
			b1=new bool[n];
			b2=new bool[n];
			u=new nint[n];
			var pq=new Rheap<int>(32);
			z[s]=0;
			l[s]=-1;
			u[s]=inf;
			b2[s]=true;
			pq.Push(new Rheap<int>.Dt(0,s));
			bo=false;
			while(pq.cnt>0){
				var e=pq.Dequeue;
				if(b1[e.d]){continue;}
				b1[e.d]=true;
				if(e.d==t){bo=true;}
				for(int i=0;i<li[e.d].Count;i++){
					if(h[li[e.d][i]].e==0){continue;}
					nint co=e.n+h[li[e.d][i]].c-pt[k^1][h[li[e.d][i]].n]+pt[k^1][e.d];
					if(!b2[h[li[e.d][i]].n]||z[h[li[e.d][i]].n]>co){
						b2[h[li[e.d][i]].n]=true;
						z[h[li[e.d][i]].n]=co;
						pt[k][h[li[e.d][i]].n]=pt[k^1][h[li[e.d][i]].n]+co;
						l[h[li[e.d][i]].n]=e.d;
						r[h[li[e.d][i]].n]=li[e.d][i];
						u[h[li[e.d][i]].n]=Min(u[e.d],h[li[e.d][i]].e);
						pq.Push(new Rheap<int>.Dt(z[h[li[e.d][i]].n],h[li[e.d][i]].n));
					}
					else if(z[h[li[e.d][i]].n]==co){
						var o=Min(u[e.d],h[li[e.d][i]].e);
						if(u[h[li[e.d][i]].n]<o){
							u[h[li[e.d][i]].n]=o;
							l[h[li[e.d][i]].n]=e.d;
							r[h[li[e.d][i]].n]=li[e.d][i];
						}
					}
				}
			}
			if(!bo){break;}
			u[t]=(int)Min(c-d,u[t]);
			for(int i = t;i!=s;i=l[i]) {
				ans+=u[t]*h[r[i]].c;
				h[r[i]].e-=u[t];
				h[r[i]^1].e+=u[t];
			}
			k^=1;
			d+=u[t];
		}
		return c==d?ans:-1;
	}
	public void Th(Action<int,int,nint> f){
		for(int i = 0;i<p;i+=2) {
			if(h[i+1].e!=0){
				f(h[i+1].n,h[i].n,h[i+1].e);
			}
		}
	}
}
public class Rheap<T>{
	public class Dt{
		public nint n;
		public T d;
		public Dt(nint n,T d){this.n=n;this.d=d;}
		public override string ToString()=>"d:"+d.ToString()+" n:"+n.ToString();
	}
	private const int m=65;
	private nint la=0;
	private Dt[][] bf;
	private int[] h;
	public int cnt=0;
	public Rheap(int max){
		bf=new Dt[m][];
		h=new int[m];
		for(int i = 0;i<m;i++) {bf[i]=new Dt[max];}
	}
	public void Push(Dt x){
		int a=x.n!=la?Bsr(la^x.n)+1:0;
		if(h[a]==bf[a].Length){Extend(a);}
		bf[a][h[a]]=x;
		cnt++;
		h[a]++;
	}
	public Dt Peek{get{
		if(h[0]==0){
			for(int i = 1;i<m;i++) {
				if(h[i]>0){
					int p=0;
					for(int j = 1;j<h[i];j++) {
						if(bf[i][p].n>bf[i][j].n){p=j;}
					}
					la=bf[i][p].n;
					for(int j = 0;j<h[i];j++) {
						Push(bf[i][j]);
						cnt--;
					}
					h[i]=0;
					break;
				}
			}
		}
		return bf[0][h[0]-1];
	}}
	public Dt Dequeue{get{
		var e=Peek;
		h[0]--;
		cnt--;
		return e;
	}}
	private void Extend(int n){
		var nhe=new Dt[bf[n].Length<<1];
		Array.Copy(bf[n],nhe,bf[n].Length);
		bf[n]=nhe;
	}
	private int Bsr(long b){
		int n=0;
		if(b==0){return -1;}
		if((b&-4294967296)!=0){b=b&-4294967296;n+=32;}
		if((b&-281470681808896)!=0){b=b&-281470681808896;n+=16;}
		if((b&-71777214294589696)!=0){b=b&-71777214294589696;n+=8;}
		if((b&-1085102592571150096)!=0){b=b&-1085102592571150096;n+=4;}
		if((b&-3689348814741910324)!=0){b=b&-3689348814741910324;n+=2;}
		if((b&-6148914691236517206)!=0){b=b&-6148914691236517206;n+=1;}
		return n;
	}
}
public class Sc{
	public int I{get{return int.Parse(Console.ReadLine());}}
	public long L{get{return long.Parse(Console.ReadLine());}}
	public double D{get{return double.Parse(Console.ReadLine());}}
	public string S{get{return Console.ReadLine();}}
	public int[] Ia{get{return Array.ConvertAll(Console.ReadLine().Split(),int.Parse);}}
	public long[] La{get{return Array.ConvertAll(Console.ReadLine().Split(),long.Parse);}}
	public double[] Da{get{return Array.ConvertAll(Console.ReadLine().Split(),double.Parse);}}
	public string[] Sa{get{return Console.ReadLine().Split();}}
	public object[] Oa{get{return Console.ReadLine().Split();}}
	public int[] Ia2{get{return Array.ConvertAll(("0 "+Console.ReadLine()+" 0").Split(),int.Parse);}}
	public int[] Ia3(string a,string b){return Array.ConvertAll((a+Console.ReadLine()+b).Split(),int.Parse);}
	public long[] La2{get{return Array.ConvertAll(("0 "+Console.ReadLine()+" 0").Split(),long.Parse);}}
	public long[] La3(string a,string b){return Array.ConvertAll((a+Console.ReadLine()+b).Split(),long.Parse);}
	public double[] Da2{get{return Array.ConvertAll(("0 "+Console.ReadLine()+" 0").Split(),double.Parse);}}
	public double[] Da3(string a,string b){return Array.ConvertAll((a+Console.ReadLine()+b).Split(),double.Parse);}
	public T[] Arr<T>(int n,Func<T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f();}return a;}
	public T[] Arr<T>(int n,Func<int,T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f(i);}return a;}
	public T[] Arr<T>(int n,Func<string[],T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f(Console.ReadLine().Split());}return a;}
	public T[] Arr<T>(int n,Func<int,string[],T> f){var a=new T[n];for(int i=0;i<n;i++){a[i]=f(i,Console.ReadLine().Split());}return a;}
}