import java.io.BufferedReader

fun main() = aising2019c()

@OptIn(ExperimentalStdlibApi::class)
fun aising2019c() = SimpleIO_aising2019c().exec {
    val (h, w) = readLine().split(" ").map { it.toInt() }
    val board = Array(h) { readLine().map { it == '#' }.toBooleanArray() }

    val around = listOf(-1 to 0, 1 to 0, 0 to -1, 0 to 1)
    val visited = Array(h) { BooleanArray(w) }
    var answer = 0L

    for (i in 0 until h) for (j in 0 until w) {
        if (!board[i][j] || visited[i][j]) continue

        var blackCount = 0L
        var whiteCount = 0L

        fun dfs(y: Int, x: Int) {
            if (visited[y][x]) return else visited[y][x] = true
            if (board[y][x]) blackCount++ else whiteCount++
            around.map { y - it.first to x - it.second }
                .filter { (ny, nx) -> ny in 0 until h && nx in 0 until w && board[ny][nx] != board[y][x] }
                .forEach { (ny, nx) -> dfs(ny, nx) }
        }

        dfs(i, j)

        answer += blackCount * whiteCount
    }

    println(answer)
}

// region kokokara template dayo (^o^)
@Suppress("unused", "HasPlatformType", "MemberVisibilityCanBePrivate", "ClassName")
private class SimpleIO_aising2019c(private val separator: String = System.lineSeparator()) {
    private val br: BufferedReader = System.`in`.bufferedReader()
    private val sb: StringBuilder = StringBuilder()
    fun readLine(): String = br.readLine()!!
    fun println(): Unit = run { sb.append(separator) }
    fun print(any: Any): Unit = run { sb.append(any) }
    fun println(any: Any): Unit = print(any.toString() + separator)
    fun exec(action: SimpleIO_aising2019c.() -> Unit) = run {
        Thread(null, { action() }, "(^o^)", 128 * 1024 * 1024).apply { start() }.join()
    }.run { kotlin.io.print(sb) }
}
// endregion kokomade template dayo (^o^)
