// Original C++ solution (slower):
#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cstring>



#include <iostream>

#include <complex>

#include <string>

#include <algorithm>

#include <numeric>

#include <vector>

#include <queue>

#include <stack>

#include <map>

#include <set>

#include <unordered_map>

#include <unordered_set>



#include <functional>

#include <cassert>



typedef long long ll;

using namespace std;



#ifndef LOCAL

#define debug(x) ;

#else

#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;



template <typename T1, typename T2>

ostream &operator<<(ostream &out, const pair<T1, T2> &p) {

  out << "{" << p.first << ", " << p.second << "}";

  return out;

}



template <typename T>

ostream &operator<<(ostream &out, const vector<T> &v) {

  out << '{';

  for (const T &item : v) out << item << ", ";

  out << "\b\b}";

  return out;

}

#endif



#define mod 1000000007 //1e9+7(prime number)

#define INF 1000000000 //1e9

#define LLINF 2000000000000000000LL //2e18

#define SIZE 510



int h, w;

char s[SIZE][SIZE];



int dx[8] = {0,0,1,-1,1,1,-1,-1};

int dy[8] = {1,-1,0,0,1,-1,1,-1};

char dirchar[] = "DURL"; // "SNWE"



pair<int,int> memo[SIZE][SIZE] = {};

ll ans[SIZE][SIZE] = {};



int check(int Y, int X) {

  bool visited[SIZE][SIZE] = {};



  if (s[Y][X] != '#') return 0;



  queue<pair<int,int> > que;

  que.push({Y,X});



  int res = 0;



  while(que.size()){

    auto p = que.front();

    que.pop();



    int y = p.first;

    int x = p.second;



    if(visited[y][x]) continue;

    visited[y][x] = true;



    debug(memo[y][x]);

    if(memo[y][x].first != -1) {

      return ans[Y][X] = ans[memo[y][x].first][memo[y][x].second];

    }

    memo[y][x] = {Y, X};



    res += s[y][x] != '#';



    for(int i=0;i<4;i++){

      if(0 <= y+dy[i] && y+dy[i] < h && 0<= x+dx[i] && x+dx[i] < w &&

         s[y][x] != s[y+dy[i]][x+dx[i]]){

        que.push({y+dy[i], x+dx[i]});

      }

    }

  }



  ans[Y][X] = res;



  return res;

}



int main(){



  scanf("%d%d", &h, &w);



  for(int i=0;i<h;i++){

    scanf("%s", s[i]);

  }



  for(int i=0;i<h;i++)

    for(int j=0;j<w;j++)

      memo[i][j] = {-1, -1};



  ll ans = 0;



  for(int i=0;i<h;i++)

    for(int j=0;j<w;j++)

      ans += check(i, j);



  cout << ans << endl;



  return 0;

}


// Optimized solution to the same problem (faster):
#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cstring>



#include <iostream>

#include <complex>

#include <string>

#include <algorithm>

#include <numeric>

#include <vector>

#include <queue>

#include <stack>

#include <map>

#include <set>

#include <unordered_map>

#include <unordered_set>



#include <functional>

#include <cassert>



typedef long long ll;

using namespace std;



#ifndef LOCAL

#define debug(x) ;

#else

#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;



template <typename T1, typename T2>

ostream &operator<<(ostream &out, const pair<T1, T2> &p) {

  out << "{" << p.first << ", " << p.second << "}";

  return out;

}



template <typename T>

ostream &operator<<(ostream &out, const vector<T> &v) {

  out << '{';

  for (const T &item : v) out << item << ", ";

  out << "\b\b}";

  return out;

}

#endif



#define mod 1000000007 //1e9+7(prime number)

#define INF 1000000000 //1e9

#define LLINF 2000000000000000000LL //2e18

#define SIZE 510



int h, w;

char s[SIZE][SIZE];



int dx[8] = {0,0,1,-1,1,1,-1,-1};

int dy[8] = {1,-1,0,0,1,-1,1,-1};

char dirchar[] = "DURL"; // "SNWE"



pair<int,int> memo[SIZE][SIZE] = {};

ll ans[SIZE][SIZE] = {};



int check(int Y, int X) {



  if (s[Y][X] != '#') return 0;



  queue<pair<int,int> > que;

  que.push({Y,X});



  int res = 0;



  while(que.size()){

    auto p = que.front();

    que.pop();



    int y = p.first;

    int x = p.second;



    if(memo[y][x].first == Y && memo[y][x].second == X) continue;



    debug(memo[y][x]);

    if(memo[y][x].first != -1) {

      return ans[Y][X] = ans[memo[y][x].first][memo[y][x].second];

    }

    memo[y][x] = {Y, X};



    res += s[y][x] != '#';



    for(int i=0;i<4;i++){

      if(0 <= y+dy[i] && y+dy[i] < h && 0<= x+dx[i] && x+dx[i] < w &&

         s[y][x] != s[y+dy[i]][x+dx[i]]){

        que.push({y+dy[i], x+dx[i]});

      }

    }

  }



  ans[Y][X] = res;



  return res;

}



int main(){



  scanf("%d%d", &h, &w);



  for(int i=0;i<h;i++){

    scanf("%s", s[i]);

  }



  for(int i=0;i<h;i++)

    for(int j=0;j<w;j++)

      memo[i][j] = {-1, -1};



  ll ans = 0;



  for(int i=0;i<h;i++)

    for(int j=0;j<w;j++)

      ans += check(i, j);



  cout << ans << endl;



  return 0;

}


// Fastest known solution for this problem: