#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <fstream>
#include <cassert>
#include <cstring>
#include <unordered_set>
#include <unordered_map>
#include <numeric>
#include <ctime>
#include <bitset>
#include <complex>
#include <chrono>
#include <random>
#include <functional>

using namespace std;

typedef long long ll;

const int N = 401;
const vector<int> dx = {0, 0, 1, -1};
const vector<int> dy = {1, -1, 0, 0};

int used[N * N];
vector<int> g[N * N];

int n, m;
int a[N][N];

int get(int i, int j) {
	return i * m + j;
}

int ok(int i, int j) {
	return 0 <= i & i < n && 0 <= j && j < m;
}

void dfs(int cur, int &c0, int &c1) {
	used[cur] = 1;
	if (a[cur / m][cur % m] == 0) {
		c0++;
	} else {
		c1++;
	}
	for (auto t : g[cur]) {
		if (!used[t]) {
			dfs(t, c0, c1);
		}
	}
}

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0);

	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			char c;
			cin >> c;
			a[i][j] = (c == '#');
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			for (int f = 0; f < 4; f++) {
				int i1 = i + dx[f];
				int j1 = j + dy[f];
				if (ok(i1, j1) && a[i][j] != a[i1][j1]) {
					g[get(i, j)].push_back(get(i1, j1));
				}
			}
		}
	}
	ll ans = 0;
	for (int i = 0; i < n * m; i++) {
		if (!used[i]) {
			int c0 = 0;
			int c1 = 0;
			dfs(i, c0, c1);
			ans += c0 * c1;
		}
	}
	cout << ans << '\n';
}

#include<bits/stdc++.h> 
using namespace std;
typedef long long int ll;
typedef vector<ll> vi;
typedef pair<ll,ll> pii;
#define fo(i,s,e_ex) for(i=s;i<e_ex;i++)
#define Fo(i,k,n) for(i=k;k<n?i<=n:i>=n;k<n?i+=1:i-=1)
#define endl '\n'
#define MOD 1000000007//998244353
#define pbb push_back
#define mpp make_pair
#define setbits(x) __builtin_popcountll(x)
#define ff first
#define ss second
#define all(x) x.begin(),x.end()
#define mset(arr,val) memset(arr,val,sizeof(arr))
ll a[20][20],n;
ll dp[66000],gc[66000];
vi sm[66000];
bool dpp[66000];
void findsm(ll pos,ll bitmask,ll submask){
    if(pos==n){
        if(setbits(submask)==0) return;
        sm[bitmask].pbb(submask);
        return;
    }
    findsm(pos+1,bitmask,submask);
    findsm(pos+1,bitmask|(1<<pos),submask);
    findsm(pos+1,bitmask|(1<<pos),submask|(1<<pos));
}
void findgc(){
    for(ll b=1;b<pow(2,n);b++){
        //b is the bitmask
        gc[b]=0;
        for(ll i=0;i<n;i++){
            if(        ((1<<i) & b)==0   ) continue;
            for(ll j=i+1;j<n;j++){
                if(        ((1<<j) & b)==0   ) continue;
                gc[b]+=a[i][j];
            }
        }
    }
}
ll findans(ll bitmask){
    if(bitmask==0) return 0;
    if(dpp[bitmask]) return dp[bitmask];
    ll ans=LLONG_MIN;
    for(auto submask:sm[bitmask]){
        ans = max(ans,findans(bitmask^submask)+gc[submask]);
    }
    dpp[bitmask]=true;
    return dp[bitmask]=ans;
}
void solve(ll caseno){
	ll i,j,ans;
    cin>>n;
    fo(i,0,n){
        fo(j,0,n){
            cin>>a[i][j];
        }
    }
    findsm(0,0,0);
    findgc();
    mset(dpp,0);
    ans = findans(pow(2,n)-1);
    cout<<ans<<endl;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	ll t=1;
	//cin>>t;
	for(ll i=1;i<=t;i++){
		solve(i);
	}
	return 0;
}
