#include <bits/stdc++.h>
using namespace std;
#define all(n) begin(n), end(n)
const long long INF = numeric_limits<long long>::max();
typedef long long ll;
typedef vector<int> vint;
typedef vector<vector<int>> vvint;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef unsigned long long ull;
template <class T>
bool chmax(T &a, const T &b)
{
    if (a < b)
    {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T &a, const T &b)
{
    if (b < a)
    {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }

template <typename T, typename... Ts>
auto make_v(size_t a, Ts... ts)
{
    return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}
template <typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type
fill_v(T &t, const V &v) { t = v; }

template <typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type
fill_v(T &t, const V &v)
{
    for (auto &e : t)
        fill_v(e, v);
}
int value(int y,int x)
{
    return 500*y+x;
}
struct UnionFind
{
    vector<int> data;

    UnionFind(int sz)
    {
        data.assign(sz, -1);
    }

    bool unite(int x, int y)
    {
        x = find(x), y = find(y);
        if (x == y)
            return (false);
        if (data[x] > data[y])
            swap(x, y);
        data[x] += data[y];
        data[y] = x;
        return (true);
    }

    int find(int k)
    {
        if (data[k] < 0)
            return (k);
        return (data[k] = find(data[k]));
    }

    int size(int k)
    {
        return (-data[find(k)]);
    }
    bool same(int x, int y)
    {
        return find(x) == find(y);
    }
};
const int M = 500*500;
UnionFind uf(M);
vector<vector<char>> s;
int H,W;
const int dx[] = {1,0,-1,0};
const int dy[] = {0,1,0,-1};
vector<vector<int>> seen;
void dfs(int y,int x)
{
    char cur = s[y][x];
    for (size_t i = 0; i < 4; i++)
    {

            int ny = y + dy[i];
            int nx = x + dx[i];
            if(0 <= ny and ny < H and 0 <= nx and nx < W and !uf.same(value(ny,nx),value(y,x)))
            {
                if(s[ny][nx] != cur)
                {
                    uf.unite(value(ny,nx),value(y,x));
                    dfs(ny,nx);
                }
                
            }
        
    }
    
}
int main()
{
    
    cin>>H>>W;
    s = make_v<char>(H,W);
    seen = make_v<int>(H,W);
    for (size_t i = 0; i < H; i++)
    {
        for (size_t j = 0; j < W; j++)
        {
            cin>>s[i][j];
        }
    }
    for (size_t i = 0; i < H; i++)
    {
        for (size_t j = 0; j < W; j++)
        {
            dfs(i,j);
        }
    }
    map<ll,pair<ll,ll>> cnt;
    for (size_t i = 0; i < H; i++)
    {
        for (size_t j = 0; j < W; j++)
        {
            if(s[i][j]=='.')
            cnt[uf.find(value(i,j))].first++;
            else
            cnt[uf.find(value(i,j))].second++;
        }
        
    }
    for (size_t i = 0; i < H; i++)
    {
        for (size_t j = 0; j < W; j++)
        {
 //           cout<<uf.size(value(i,j))<<" ";
        }
 //       cout<<endl;
    }
    
    ll ans = 0;
    for (auto &&i : cnt)
    {
        ans += (i.second.first*i.second.second);
    }
    cout<<ans;
    
    return 0;
}

Measured memory_bytes: 29568