package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

type edge struct {
	from   int
	to     int
	weight int
}

type minHeap struct {
	size          int
	vals          []int
	lookup        []int
	reverseLookup []int
}

func (h *minHeap) heapify(i int) {
	for i > 0 {
		parent := (i - 1) / 2
		if h.vals[i] < h.vals[parent] {
			h.swap(i, parent)
			i = parent
		} else {
			return
		}
	}
}

func (h *minHeap) pop() {
	h.swap(0, h.size-1)
	h.size--
	i := 0
	for {
		better := i
		if i*2+1 < h.size && h.vals[i*2+1] < h.vals[better] {
			better = i*2 + 1
		}
		if i*2+2 < h.size && h.vals[i*2+2] < h.vals[better] {
			better = i*2 + 2
		}
		if better != i {
			h.swap(i, better)
			i = better
		} else {
			break
		}
	}
}

func (h *minHeap) swap(i int, j int) {
	t := h.vals[i]
	h.vals[i] = h.vals[j]
	h.vals[j] = t

	ri := h.reverseLookup[i]
	rj := h.reverseLookup[j]

	h.lookup[ri] = j
	h.lookup[rj] = i

	t = h.reverseLookup[i]
	h.reverseLookup[i] = h.reverseLookup[j]
	h.reverseLookup[j] = t
}

const inf = 9223372036854775807

// https://codeforces.com/problemset/problem/1727/M
func P1727m(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var m int
	fmt.Fscan(in, &m)

	var incoming = make([][]edge, n+1)
	var outgoing = make([][]edge, n+1)

	for i := 0; i <= n; i++ {
		incoming[i] = make([]edge, 0)
		outgoing[i] = make([]edge, 0)
	}

	for i := 0; i < m; i++ {
		var from int
		var to int
		var weight int
		fmt.Fscan(in, &from)
		fmt.Fscan(in, &to)
		fmt.Fscan(in, &weight)

		var e = edge{from: from, to: to, weight: weight}
		outgoing[from] = append(outgoing[from], e)
		incoming[to] = append(incoming[to], e)
	}

	dist1 := make([]int, n+1)
	lookup1 := make([]int, n+1)
	reverseLookup1 := make([]int, n+1)
	vals1 := make([]int, n+1)
	for i := range dist1 {
		dist1[i] = inf
		vals1[i] = inf
		lookup1[i] = i
		reverseLookup1[i] = i
	}
	vals1[1] = 0
	heap1 := minHeap{
		size:          n + 1,
		vals:          vals1,
		lookup:        lookup1,
		reverseLookup: reverseLookup1,
	}
	heap1.heapify(1)

	for heap1.size > 0 {
		if heap1.vals[0] >= inf {
			break
		}
		topVal := heap1.vals[0]
		topV := heap1.reverseLookup[0]
		dist1[topV] = topVal
		heap1.pop()
		for _, e := range outgoing[topV] {
			neww := dist1[topV] + e.weight
			topos := heap1.lookup[e.to]
			if neww < heap1.vals[topos] {
				heap1.vals[topos] = neww
				heap1.heapify(topos)
			}
		}
	}

	distR := make([]int, n+1)
	lookupR := make([]int, n+1)
	reverseLookupR := make([]int, n+1)
	valsR := make([]int, n+1)
	for i := range distR {
		distR[i] = dist1[i]
		valsR[i] = dist1[i]
		lookupR[i] = i
		reverseLookupR[i] = i
	}
	heapR := minHeap{
		size:          n + 1,
		vals:          valsR,
		lookup:        lookupR,
		reverseLookup: reverseLookupR,
	}
	for i := 0; i <= n; i++ {
		heapR.heapify(i)
	}
	for heapR.size > 0 {
		if heapR.vals[0] >= inf {
			break
		}
		topVal := heapR.vals[0]
		topV := heapR.reverseLookup[0]
		distR[topV] = topVal
		heapR.pop()
		for _, e := range incoming[topV] {
			neww := distR[topV] + e.weight
			frompos := heapR.lookup[e.from]
			if neww < heapR.vals[frompos] {
				heapR.vals[frompos] = neww
				heapR.heapify(frompos)
			}
		}
	}
	var resToJoin []string
	for _, x := range distR[2:] {
		if x < inf {
			resToJoin = append(resToJoin, strconv.Itoa(x))

		} else {
			resToJoin = append(resToJoin, "-1")

		}
	}
	result := strings.Join(resToJoin, " ")
	fmt.Fprintf(out, result)
}

func main() { P1727m(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
)

type Neighbor struct {
	label int
	cost int
}

type NodeHeap []Neighbor

func (h NodeHeap) Len() int           { return len(h) }
func (h NodeHeap) Less(i, j int) bool { return h[i].cost < h[j].cost }
func (h NodeHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *NodeHeap) Push(x any) {
	*h = append(*h, x.(Neighbor))
}

func (h *NodeHeap) Pop() any {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func main() {
	r := bufio.NewReader(os.Stdin)
	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()

	var n, m, u, v, wt int
	fmt.Fscan(r, &n, &m)

	adj := make([][]Neighbor, 2*n)

	for i := 0; i < m; i++ {
		fmt.Fscan(r, &u, &v, &wt)
		adj[u - 1] = append(adj[u - 1], Neighbor{v - 1, wt})
		adj[n + v - 1] = append(adj[n + v - 1], Neighbor{n + u - 1, wt})
	}

	for i := 0; i < n; i++ {
		adj[i] = append(adj[i], Neighbor{n + i, 0})
	}

	visited := make(map[int]bool)
	distance := make(map[int]int)
	distance[0] = 0

	h := &NodeHeap{}
	heap.Init(h)
	heap.Push(h, Neighbor{0, 0})

	for h.Len() > 0 {
		node := heap.Pop(h).(Neighbor)
		label := node.label
		if visited[label] {
			continue
		}
		visited[label] = true

		for _, nbr := range adj[label] {
			cost, prs := distance[nbr.label]
			cost_through_node := distance[label] + nbr.cost
			if !prs || cost_through_node < cost {
				distance[nbr.label] = cost_through_node
				heap.Push(h, Neighbor{nbr.label, cost_through_node})
			}
		}
	}

	for i := n + 1; i < 2*n; i++ {
		cost, prs := distance[i]
		if !prs {
			cost = -1
		}
		fmt.Fprintf(w, "%d ", cost)
	}
	fmt.Fprint(w, "\n")

}

package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
)

type Neighbor struct {
	label int
	cost int
}

type NodeHeap []Neighbor

func (h NodeHeap) Len() int           { return len(h) }
func (h NodeHeap) Less(i, j int) bool { return h[i].cost < h[j].cost }
func (h NodeHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *NodeHeap) Push(x any) {
	*h = append(*h, x.(Neighbor))
}

func (h *NodeHeap) Pop() any {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func main() {
	r := bufio.NewReader(os.Stdin)
	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()

	var n, m, u, v, wt int
	fmt.Fscan(r, &n, &m)

	adj := make([][]Neighbor, 2*n)

	for i := 0; i < m; i++ {
		fmt.Fscan(r, &u, &v, &wt)
		adj[u - 1] = append(adj[u - 1], Neighbor{v - 1, wt})
		adj[n + v - 1] = append(adj[n + v - 1], Neighbor{n + u - 1, wt})
	}

	for i := 0; i < n; i++ {
		adj[i] = append(adj[i], Neighbor{n + i, 0})
	}

	visited := make(map[int]bool)
	distance := make(map[int]int)
	distance[0] = 0

	h := &NodeHeap{}
	heap.Init(h)
	heap.Push(h, Neighbor{0, 0})

	for h.Len() > 0 {
		node := heap.Pop(h).(Neighbor)
		label := node.label
		// fmt.Fprintln(w, "+++++++++ ", label)
		if visited[label] {
			continue
		}
		visited[label] = true

		for _, nbr := range adj[label] {
			cost, prs := distance[nbr.label]
			cost_through_node := distance[label] + nbr.cost
			if !prs || cost_through_node < cost {
				distance[nbr.label] = cost_through_node
				heap.Push(h, Neighbor{nbr.label, cost_through_node})
				// fmt.Fprintln(w, "********* ", nbr.label, cost_through_node)
			}
		}
	}

	for i := n + 1; i < 2*n; i++ {
		cost, prs := distance[i]
		if !prs {
			cost = -1
		}
		fmt.Fprintf(w, "%d ", cost)
	}
	fmt.Fprint(w, "\n")

}

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

type edge struct {
	from   int
	to     int
	weight int
}

type minHeap struct {
	size          int
	vals          []int
	lookup        []int
	reverseLookup []int
}

func (h *minHeap) heapify(i int) {
	for i > 0 {
		parent := (i - 1) / 2
		if h.vals[i] < h.vals[parent] {
			h.swap(i, parent)
			i = parent
		} else {
			return
		}
	}
}

func (h *minHeap) pop() {
	h.swap(0, h.size-1)
	h.size--
	i := 0
	for {
		better := i
		if i*2+1 < h.size && h.vals[i*2+1] < h.vals[better] {
			better = i*2 + 1
		}
		if i*2+2 < h.size && h.vals[i*2+2] < h.vals[better] {
			better = i*2 + 2
		}
		if better != i {
			h.swap(i, better)
			i = better
		} else {
			break
		}
	}
}

func (h *minHeap) swap(i int, j int) {
	// fmt.Printf("### Swapping %d and %d\n", i, j)
	t := h.vals[i]
	h.vals[i] = h.vals[j]
	h.vals[j] = t

	ri := h.reverseLookup[i]
	rj := h.reverseLookup[j]

	// fmt.Printf("### Lookup %d <-> %d, reverse: %d <-> %d\n", h.lookup[ri], h.lookup[rj], ri, rj)

	// t = h.lookup[ri]
	// h.lookup[ri] = h.lookup[rj]
	// h.lookup[rj] = t
	h.lookup[ri] = j
	h.lookup[rj] = i

	t = h.reverseLookup[i]
	h.reverseLookup[i] = h.reverseLookup[j]
	h.reverseLookup[j] = t

}

const inf = 9223372036854775807

// https://codeforces.com/problemset/problem/1727/M
func P1727m(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var m int
	fmt.Fscan(in, &m)

	var incoming = make([][]edge, n+1)
	var outgoing = make([][]edge, n+1)

	for i := 0; i <= n; i++ {
		incoming[i] = make([]edge, 0)
		outgoing[i] = make([]edge, 0)
	}

	for i := 0; i < m; i++ {
		var from int
		var to int
		var weight int
		fmt.Fscan(in, &from)
		fmt.Fscan(in, &to)
		fmt.Fscan(in, &weight)

		var e = edge{from: from, to: to, weight: weight}
		outgoing[from] = append(outgoing[from], e)
		incoming[to] = append(incoming[to], e)
	}

	dist1 := make([]int, n+1)
	lookup1 := make([]int, n+1)
	reverseLookup1 := make([]int, n+1)
	vals1 := make([]int, n+1)
	for i := range dist1 {
		dist1[i] = inf
		vals1[i] = inf
		lookup1[i] = i
		reverseLookup1[i] = i
	}
	vals1[1] = 0
	heap1 := minHeap{
		size:          n + 1,
		vals:          vals1,
		lookup:        lookup1,
		reverseLookup: reverseLookup1,
	}
	heap1.heapify(1)

	for heap1.size > 0 {
		if heap1.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, vals: %v\n", vals1)
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heap1.vals[0]
		topV := heap1.reverseLookup[0]
		// fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		dist1[topV] = topVal
		heap1.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range outgoing[topV] {
			neww := dist1[topV] + e.weight
			topos := heap1.lookup[e.to]
			if neww < heap1.vals[topos] {
				// fmt.Printf("### Found improvement. v=%d, neww=%d, topos=%d\n", e.to, neww, topos)
				heap1.vals[topos] = neww
				heap1.heapify(topos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}

	// fmt.Printf("### Dist1: %v\n", dist1)

	distR := make([]int, n+1)
	lookupR := make([]int, n+1)
	reverseLookupR := make([]int, n+1)
	valsR := make([]int, n+1)
	for i := range distR {
		distR[i] = dist1[i]
		valsR[i] = dist1[i]
		lookupR[i] = i
		reverseLookupR[i] = i
	}
	heapR := minHeap{
		size:          n + 1,
		vals:          valsR,
		lookup:        lookupR,
		reverseLookup: reverseLookupR,
	}
	// fmt.Printf("### DistR pre heapify: %v\n", distR)
	for i := 0; i <= n; i++ {
		heapR.heapify(i)
	}
	// for i := n - 1; i > 0; i-- {
	// 	heapR.heapify(i)
	// }
	// fmt.Printf("### DistR post heapify: %v\n", distR)

	for heapR.size > 0 {
		//fmt.Printf("### Iteration, vals: %v\n", valsR)
		if heapR.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heapR.vals[0]
		topV := heapR.reverseLookup[0]
		//fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		distR[topV] = topVal
		heapR.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range incoming[topV] {
			neww := distR[topV] + e.weight
			frompos := heapR.lookup[e.from]
			if neww < heapR.vals[frompos] {
				//fmt.Printf("### Found improvement. v=%d, neww=%d, frompos=%d\n", e.to, neww, frompos)
				heapR.vals[frompos] = neww
				heapR.heapify(frompos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}
	//fmt.Printf("### DistsR: %v\n", distR)
	var resToJoin []string
	for _, x := range distR[2:] {
		if x < inf {
			resToJoin = append(resToJoin, strconv.Itoa(x))

		} else {
			resToJoin = append(resToJoin, "-1")

		}
	}
	result := strings.Join(resToJoin, " ")
	fmt.Fprintf(out, result)
}

func main() { P1727m(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

type edge struct {
	from   int
	to     int
	weight int
}

type minHeap struct {
	size          int
	vals          []int
	lookup        []int
	reverseLookup []int
}

func (h *minHeap) heapify(i int) {
	for i > 0 {
		parent := (i - 1) / 2
		if h.vals[i] < h.vals[parent] {
			h.swap(i, parent)
			i = parent
		} else {
			return
		}
	}
}

func (h *minHeap) pop() {
	h.swap(0, h.size-1)
	h.size--
	i := 0
	for {
		better := i
		if i*2+1 < h.size && h.vals[i*2+1] < h.vals[better] {
			better = i*2 + 1
		}
		if i*2+2 < h.size && h.vals[i*2+2] < h.vals[better] {
			better = i*2 + 2
		}
		if better != i {
			h.swap(i, better)
			i = better
		} else {
			break
		}
	}
}

func (h *minHeap) swap(i int, j int) {
	// fmt.Printf("### Swapping %d and %d\n", i, j)
	t := h.vals[i]
	h.vals[i] = h.vals[j]
	h.vals[j] = t

	ri := h.reverseLookup[i]
	rj := h.reverseLookup[j]

	// fmt.Printf("### Lookup %d <-> %d, reverse: %d <-> %d\n", h.lookup[ri], h.lookup[rj], ri, rj)

	// t = h.lookup[ri]
	// h.lookup[ri] = h.lookup[rj]
	// h.lookup[rj] = t
	h.lookup[ri] = j
	h.lookup[rj] = i

	t = h.reverseLookup[i]
	h.reverseLookup[i] = h.reverseLookup[j]
	h.reverseLookup[j] = t

}

const inf = 9223372036854775807

// https://codeforces.com/problemset/problem/1727/M
func P1727m(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var m int
	fmt.Fscan(in, &m)

	var incoming = make([][]edge, n+1)
	var outgoing = make([][]edge, n+1)

	for i := 0; i <= n; i++ {
		incoming[i] = make([]edge, 0)
		outgoing[i] = make([]edge, 0)
	}

	for i := 0; i < m; i++ {
		var from int
		var to int
		var weight int
		fmt.Fscan(in, &from)
		fmt.Fscan(in, &to)
		fmt.Fscan(in, &weight)

		var e = edge{from: from, to: to, weight: weight}
		outgoing[from] = append(outgoing[from], e)
		incoming[to] = append(incoming[to], e)
	}

	dist1 := make([]int, n+1)
	lookup1 := make([]int, n+1)
	reverseLookup1 := make([]int, n+1)
	vals1 := make([]int, n+1)
	for i := range dist1 {
		dist1[i] = inf
		vals1[i] = inf
		lookup1[i] = i
		reverseLookup1[i] = i
	}
	vals1[1] = 0
	heap1 := minHeap{
		size:          n + 1,
		vals:          vals1,
		lookup:        lookup1,
		reverseLookup: reverseLookup1,
	}
	heap1.heapify(1)

	for heap1.size > 0 {
		if heap1.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, vals: %v\n", vals1)
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heap1.vals[0]
		topV := heap1.reverseLookup[0]
		// fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		dist1[topV] = topVal
		heap1.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range outgoing[topV] {
			neww := dist1[topV] + e.weight
			topos := heap1.lookup[e.to]
			if neww < heap1.vals[topos] {
				// fmt.Printf("### Found improvement. v=%d, neww=%d, topos=%d\n", e.to, neww, topos)
				heap1.vals[topos] = neww
				heap1.heapify(topos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}

	// fmt.Printf("### Dist1: %v\n", dist1)

	distR := make([]int, n+1)
	lookupR := make([]int, n+1)
	reverseLookupR := make([]int, n+1)
	valsR := make([]int, n+1)
	for i := range distR {
		distR[i] = dist1[i]
		valsR[i] = dist1[i]
		lookupR[i] = i
		reverseLookupR[i] = i
	}
	valsR[1] = 0
	heapR := minHeap{
		size:          n + 1,
		vals:          valsR,
		lookup:        lookupR,
		reverseLookup: reverseLookupR,
	}
	// fmt.Printf("### DistR pre heapify: %v\n", distR)
	for i := n - 1; i > 0; i-- {
		heapR.heapify(i)
	}
	// fmt.Printf("### DistR post heapify: %v\n", distR)

	for heapR.size > 0 {
		//fmt.Printf("### Iteration, vals: %v\n", valsR)
		if heapR.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heapR.vals[0]
		topV := heapR.reverseLookup[0]
		//fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		distR[topV] = topVal
		heapR.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range incoming[topV] {
			neww := distR[topV] + e.weight
			frompos := heapR.lookup[e.from]
			if neww < heapR.vals[frompos] {
				//fmt.Printf("### Found improvement. v=%d, neww=%d, frompos=%d\n", e.to, neww, frompos)
				heapR.vals[frompos] = neww
				heapR.heapify(frompos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}
	//fmt.Printf("### DistsR: %v\n", distR)
	var resToJoin []string
	for _, x := range distR[2:] {
		if x < inf {
			resToJoin = append(resToJoin, strconv.Itoa(x))

		} else {
			resToJoin = append(resToJoin, "-1")

		}
	}
	result := strings.Join(resToJoin, " ")
	fmt.Fprintf(out, result)
}

func main() { P1727m(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

type edge struct {
	from   int
	to     int
	weight int
}

type minHeap struct {
	size          int
	vals          []int
	lookup        []int
	reverseLookup []int
}

func (h *minHeap) heapify(i int) {
	for i > 0 {
		parent := i / 2
		if h.vals[i] < h.vals[parent] {
			h.swap(i, parent)
			i = parent
		} else {
			return
		}
	}
}

func (h *minHeap) pop() {
	h.swap(0, h.size-1)
	h.size--
	i := 0
	for {
		better := i
		if i*2+1 < h.size && h.vals[i*2+1] < h.vals[better] {
			better = i*2 + 1
		}
		if i*2+2 < h.size && h.vals[i*2+2] < h.vals[better] {
			better = i*2 + 2
		}
		if better != i {
			h.swap(i, better)
			i = better
		} else {
			break
		}
	}
}

func (h *minHeap) swap(i int, j int) {
	// fmt.Printf("### Swapping %d and %d\n", i, j)
	t := h.vals[i]
	h.vals[i] = h.vals[j]
	h.vals[j] = t

	ri := h.reverseLookup[i]
	rj := h.reverseLookup[j]

	// fmt.Printf("### Lookup %d <-> %d, reverse: %d <-> %d\n", h.lookup[ri], h.lookup[rj], ri, rj)

	// t = h.lookup[ri]
	// h.lookup[ri] = h.lookup[rj]
	// h.lookup[rj] = t
	h.lookup[ri] = j
	h.lookup[rj] = i

	t = h.reverseLookup[i]
	h.reverseLookup[i] = h.reverseLookup[j]
	h.reverseLookup[j] = t

}

const inf = 9223372036854775807

// https://codeforces.com/problemset/problem/1727/M
func P1727m(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var m int
	fmt.Fscan(in, &m)

	var incoming = make([][]edge, n+1)
	var outgoing = make([][]edge, n+1)

	for i := 0; i <= n; i++ {
		incoming[i] = make([]edge, 0)
		outgoing[i] = make([]edge, 0)
	}

	for i := 0; i < m; i++ {
		var from int
		var to int
		var weight int
		fmt.Fscan(in, &from)
		fmt.Fscan(in, &to)
		fmt.Fscan(in, &weight)

		var e = edge{from: from, to: to, weight: weight}
		outgoing[from] = append(outgoing[from], e)
		incoming[to] = append(incoming[to], e)
	}

	dist1 := make([]int, n+1)
	lookup1 := make([]int, n+1)
	reverseLookup1 := make([]int, n+1)
	vals1 := make([]int, n+1)
	for i := range dist1 {
		dist1[i] = inf
		vals1[i] = inf
		lookup1[i] = i
		reverseLookup1[i] = i
	}
	vals1[1] = 0
	heap1 := minHeap{
		size:          n + 1,
		vals:          vals1,
		lookup:        lookup1,
		reverseLookup: reverseLookup1,
	}
	heap1.heapify(1)

	for heap1.size > 0 {
		if heap1.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, vals: %v\n", vals1)
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heap1.vals[0]
		topV := heap1.reverseLookup[0]
		// fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		dist1[topV] = topVal
		heap1.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range outgoing[topV] {
			neww := dist1[topV] + e.weight
			topos := heap1.lookup[e.to]
			if neww < heap1.vals[topos] {
				// fmt.Printf("### Found improvement. v=%d, neww=%d, topos=%d\n", e.to, neww, topos)
				heap1.vals[topos] = neww
				heap1.heapify(topos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}

	// fmt.Printf("### Dist1: %v\n", dist1)

	distR := make([]int, n+1)
	lookupR := make([]int, n+1)
	reverseLookupR := make([]int, n+1)
	valsR := make([]int, n+1)
	for i := range distR {
		distR[i] = dist1[i]
		valsR[i] = dist1[i]
		lookupR[i] = i
		reverseLookupR[i] = i
	}
	valsR[1] = 0
	heapR := minHeap{
		size:          n + 1,
		vals:          valsR,
		lookup:        lookupR,
		reverseLookup: reverseLookupR,
	}
	// fmt.Printf("### DistR pre heapify: %v\n", distR)
	for i := n - 1; i > 0; i-- {
		heapR.heapify(i)
	}
	// fmt.Printf("### DistR post heapify: %v\n", distR)

	for heapR.size > 0 {
		//fmt.Printf("### Iteration, vals: %v\n", valsR)
		if heapR.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heapR.vals[0]
		topV := heapR.reverseLookup[0]
		//fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		distR[topV] = topVal
		heapR.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range incoming[topV] {
			neww := distR[topV] + e.weight
			frompos := heapR.lookup[e.from]
			if neww < heapR.vals[frompos] {
				//fmt.Printf("### Found improvement. v=%d, neww=%d, frompos=%d\n", e.to, neww, frompos)
				heapR.vals[frompos] = neww
				heapR.heapify(frompos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}
	//fmt.Printf("### DistsR: %v\n", distR)
	var resToJoin []string
	for _, x := range distR[2:] {
		if x < inf {
			resToJoin = append(resToJoin, strconv.Itoa(x))

		} else {
			resToJoin = append(resToJoin, "-1")

		}
	}
	result := strings.Join(resToJoin, " ")
	fmt.Fprintf(out, result)
}

func main() { P1727m(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

type edge struct {
	from   int
	to     int
	weight int
}

type minHeap struct {
	size          int
	vals          []int
	lookup        []int
	reverseLookup []int
}

func (h *minHeap) heapify(i int) {
	for i > 0 {
		parent := i / 2
		if h.vals[i] < h.vals[parent] {
			h.swap(i, parent)
			i = parent
		} else {
			return
		}
	}
}

func (h *minHeap) pop() {
	h.swap(0, h.size-1)
	h.size--
	i := 0
	for {
		better := i
		if i*2+1 < h.size && h.vals[i*2+1] < h.vals[better] {
			better = i*2 + 1
		}
		if i*2+2 < h.size && h.vals[i*2+2] < h.vals[better] {
			better = i*2 + 2
		}
		if better != i {
			h.swap(i, better)
			i = better
		} else {
			break
		}
	}
}

func (h *minHeap) swap(i int, j int) {
	// fmt.Printf("### Swapping %d and %d\n", i, j)
	t := h.vals[i]
	h.vals[i] = h.vals[j]
	h.vals[j] = t

	ri := h.reverseLookup[i]
	rj := h.reverseLookup[j]

	// fmt.Printf("### Lookup %d <-> %d, reverse: %d <-> %d\n", h.lookup[ri], h.lookup[rj], ri, rj)

	// t = h.lookup[ri]
	// h.lookup[ri] = h.lookup[rj]
	// h.lookup[rj] = t
	h.lookup[ri] = j
	h.lookup[rj] = i

	t = h.reverseLookup[i]
	h.reverseLookup[i] = h.reverseLookup[j]
	h.reverseLookup[j] = t

}

const inf = 9223372036854775807

// https://codeforces.com/problemset/problem/1727/M
func P1727m(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var m int
	fmt.Fscan(in, &m)

	var incoming = make([][]edge, n+1)
	var outgoing = make([][]edge, n+1)

	for i := 0; i <= n; i++ {
		incoming[i] = make([]edge, 0)
		outgoing[i] = make([]edge, 0)
	}

	for i := 0; i < m; i++ {
		var from int
		var to int
		var weight int
		fmt.Fscan(in, &from)
		fmt.Fscan(in, &to)
		fmt.Fscan(in, &weight)

		var e = edge{from: from, to: to, weight: weight}
		outgoing[from] = append(outgoing[from], e)
		incoming[to] = append(incoming[to], e)
	}

	dist1 := make([]int, n+1)
	lookup1 := make([]int, n+1)
	reverseLookup1 := make([]int, n+1)
	vals1 := make([]int, n+1)
	for i := range dist1 {
		dist1[i] = inf
		vals1[i] = inf
		lookup1[i] = i
		reverseLookup1[i] = i
	}
	vals1[1] = 0
	heap1 := minHeap{
		size:          n + 1,
		vals:          vals1,
		lookup:        lookup1,
		reverseLookup: reverseLookup1,
	}
	heap1.heapify(1)

	for heap1.size > 0 {
		if heap1.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, vals: %v\n", vals1)
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heap1.vals[0]
		topV := heap1.reverseLookup[0]
		// fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		dist1[topV] = topVal
		heap1.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range outgoing[topV] {
			neww := dist1[topV] + e.weight
			topos := heap1.lookup[e.to]
			if neww < heap1.vals[topos] {
				// fmt.Printf("### Found improvement. v=%d, neww=%d, topos=%d\n", e.to, neww, topos)
				heap1.vals[topos] = neww
				heap1.heapify(topos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}

	fmt.Printf("### Dist1: %v\n", dist1)

	distR := make([]int, n+1)
	lookupR := make([]int, n+1)
	reverseLookupR := make([]int, n+1)
	valsR := make([]int, n+1)
	for i := range distR {
		distR[i] = dist1[i]
		valsR[i] = dist1[i]
		lookupR[i] = i
		reverseLookupR[i] = i
	}
	valsR[1] = 0
	heapR := minHeap{
		size:          n + 1,
		vals:          valsR,
		lookup:        lookupR,
		reverseLookup: reverseLookupR,
	}
	// fmt.Printf("### DistR pre heapify: %v\n", distR)
	for i := n - 1; i > 0; i-- {
		heapR.heapify(i)
	}
	// fmt.Printf("### DistR post heapify: %v\n", distR)

	for heapR.size > 0 {
		//fmt.Printf("### Iteration, vals: %v\n", valsR)
		if heapR.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heapR.vals[0]
		topV := heapR.reverseLookup[0]
		//fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		distR[topV] = topVal
		heapR.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range incoming[topV] {
			neww := distR[topV] + e.weight
			frompos := heapR.lookup[e.from]
			if neww < heapR.vals[frompos] {
				//fmt.Printf("### Found improvement. v=%d, neww=%d, frompos=%d\n", e.to, neww, frompos)
				heapR.vals[frompos] = neww
				heapR.heapify(frompos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}
	//fmt.Printf("### DistsR: %v\n", distR)
	var resToJoin []string
	for _, x := range distR[2:] {
		if x < inf {
			resToJoin = append(resToJoin, strconv.Itoa(x))

		} else {
			resToJoin = append(resToJoin, "-1")

		}
	}
	result := strings.Join(resToJoin, " ")
	fmt.Fprintf(out, result)
}

func main() { P1727m(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

type edge struct {
	from   int
	to     int
	weight int
}

type minHeap struct {
	size          int
	vals          []int
	lookup        []int
	reverseLookup []int
}

func (h *minHeap) heapify(i int) {
	for i > 0 {
		parent := i / 2
		if h.vals[i] < h.vals[parent] {
			h.swap(i, parent)
			i = parent
		} else {
			return
		}
	}
}

func (h *minHeap) pop() {
	h.swap(0, h.size-1)
	h.size--
	i := 0
	for {
		better := i
		if i*2 < h.size && h.vals[i*2] < h.vals[better] {
			better = i * 2
		}
		if i*2+1 < h.size && h.vals[i*2+1] < h.vals[better] {
			better = i*2 + 1
		}
		if better != i {
			h.swap(i, better)
			i = better
		} else {
			break
		}
	}
}

func (h *minHeap) swap(i int, j int) {
	// fmt.Printf("### Swapping %d and %d\n", i, j)
	t := h.vals[i]
	h.vals[i] = h.vals[j]
	h.vals[j] = t

	ri := h.reverseLookup[i]
	rj := h.reverseLookup[j]

	// fmt.Printf("### Lookup %d <-> %d, reverse: %d <-> %d\n", h.lookup[ri], h.lookup[rj], ri, rj)

	// t = h.lookup[ri]
	// h.lookup[ri] = h.lookup[rj]
	// h.lookup[rj] = t
	h.lookup[ri] = j
	h.lookup[rj] = i

	t = h.reverseLookup[i]
	h.reverseLookup[i] = h.reverseLookup[j]
	h.reverseLookup[j] = t

}

const inf = 9223372036854775807

// https://codeforces.com/problemset/problem/1727/M
func P1727m(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	var n int
	fmt.Fscan(in, &n)
	var m int
	fmt.Fscan(in, &m)

	var incoming = make([][]edge, n+1)
	var outgoing = make([][]edge, n+1)

	for i := 0; i <= n; i++ {
		incoming[i] = make([]edge, 0)
		outgoing[i] = make([]edge, 0)
	}

	for i := 0; i < m; i++ {
		var from int
		var to int
		var weight int
		fmt.Fscan(in, &from)
		fmt.Fscan(in, &to)
		fmt.Fscan(in, &weight)

		var e = edge{from: from, to: to, weight: weight}
		outgoing[from] = append(outgoing[from], e)
		incoming[to] = append(incoming[to], e)
	}

	dist1 := make([]int, n+1)
	lookup1 := make([]int, n+1)
	reverseLookup1 := make([]int, n+1)
	vals1 := make([]int, n+1)
	for i := range dist1 {
		dist1[i] = inf
		vals1[i] = inf
		lookup1[i] = i
		reverseLookup1[i] = i
	}
	vals1[1] = 0
	heap1 := minHeap{
		size:          n + 1,
		vals:          vals1,
		lookup:        lookup1,
		reverseLookup: reverseLookup1,
	}
	heap1.heapify(1)

	for heap1.size > 0 {
		if heap1.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, vals: %v\n", vals1)
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heap1.vals[0]
		topV := heap1.reverseLookup[0]
		// fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		dist1[topV] = topVal
		heap1.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range outgoing[topV] {
			neww := dist1[topV] + e.weight
			topos := heap1.lookup[e.to]
			if neww < heap1.vals[topos] {
				// fmt.Printf("### Found improvement. v=%d, neww=%d, topos=%d\n", e.to, neww, topos)
				heap1.vals[topos] = neww
				heap1.heapify(topos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}

	// fmt.Printf("### Dists: %v\n", dist1)

	distR := make([]int, n+1)
	lookupR := make([]int, n+1)
	reverseLookupR := make([]int, n+1)
	valsR := make([]int, n+1)
	for i := range distR {
		distR[i] = dist1[i]
		valsR[i] = dist1[i]
		lookupR[i] = i
		reverseLookupR[i] = i
	}
	valsR[1] = 0
	heapR := minHeap{
		size:          n + 1,
		vals:          valsR,
		lookup:        lookupR,
		reverseLookup: reverseLookupR,
	}
	// fmt.Printf("### DistR pre heapify: %v\n", distR)
	for i := n - 1; i > 0; i-- {
		heapR.heapify(i)
	}
	// fmt.Printf("### DistR post heapify: %v\n", distR)

	for heapR.size > 0 {
		if heapR.vals[0] >= inf {
			break
		}
		// fmt.Printf("### Iteration, vals: %v\n", valsR)
		// fmt.Printf("### Iteration, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### Iteration, reverse lookup: %v\n", heap1.reverseLookup)
		topVal := heapR.vals[0]
		topV := heapR.reverseLookup[0]
		// fmt.Printf("### Top v: %d, val: %d\n", topV, topVal)
		distR[topV] = topVal
		heapR.pop()
		// fmt.Printf("### After pop, vals: %v\n", vals1)
		// fmt.Printf("### After pop, lookup: %v\n", heap1.lookup)
		// fmt.Printf("### After pop, reverse lookup: %v\n", heap1.reverseLookup)

		for _, e := range incoming[topV] {
			neww := distR[topV] + e.weight
			frompos := heapR.lookup[e.from]
			if neww < heapR.vals[frompos] {
				// fmt.Printf("### Found improvement. v=%d, neww=%d, frompos=%d\n", e.to, neww, frompos)
				heapR.vals[frompos] = neww
				heapR.heapify(frompos)
				// fmt.Printf("### After improvement, vals: %v\n", vals1)
				// fmt.Printf("### After improvement, lookup: %v\n", heap1.lookup)
			}
		}
	}
	// fmt.Printf("### DistsR: %v\n", distR)
	var resToJoin []string
	for _, x := range distR[2:] {
		if x < inf {
			resToJoin = append(resToJoin, strconv.Itoa(x))

		} else {
			resToJoin = append(resToJoin, "-1")

		}
	}
	result := strings.Join(resToJoin, " ")
	fmt.Fprintf(out, result)
}

func main() { P1727m(os.Stdin, os.Stdout) }


package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func Sol1156D(reader io.Reader, writer io.Writer) {
	var find func([]int, int) int
	find = func(fa []int, i int) int {
		if fa[i] != i {
			fa[i] = find(fa, fa[i])
		}
		return fa[i]
	}
	merge := func(fa []int, size []int, from, to int) {
		from, to = find(fa, from), find(fa, to)
		if from != to {
			fa[from] = to
			size[to] += size[from]
		}
	}

	in := bufio.NewReader(reader)
	out := bufio.NewWriter(writer)
	defer out.Flush()

	var n int
	Fscan(in, &n)
	fa := [2][]int{}
	size := [2][]int{}
	for i := range fa {
		fa[i] = make([]int, n)
		for j := range fa[i] {
			fa[i][j] = j
		}
		size[i] = make([]int, n)
		for j := range size[i] {
			size[i][j] = 1
		}
	}
	for m := n - 1; m > 0; m-- {
		var v, w, c int
		Fscan(in, &v, &w, &c)
		merge(fa[c], size[c], v-1, w-1)
	}

	ans := int64(0)
	for i := range fa[0] {
		ans += int64(size[0][find(fa[0], i)])*int64(size[1][find(fa[1], i)]) - 1
	}
	Fprint(out, ans)
}

func main() {
	Sol1156D(os.Stdin, os.Stdout)
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

var reader = bufio.NewReader(os.Stdin)
var writer = bufio.NewWriter(os.Stdout)

func print(a ...interface{}) { fmt.Fprint(writer, a...) }
func scan(a ...interface{})  { fmt.Fscan(reader, a...) }

const (
	N int = 2e5+1
)

var (
	n int
	tree [N][][2]int
	adj [N][]int
	vis [N][2]bool
	cnt [2*N]int
)

func dfs(u int, p int, c int, id int) {
	if vis[u][c] { return }
	vis[u][c] = true
	cnt[id] += 1
	adj[u] = append(adj[u], id)
	for _,e := range tree[u] {
		v,t := e[0],e[1]
		if v!=p && t==c {
			dfs(v,u,c,id)
		}
	}
}

func main() {
	// code GOes here

	scan(&n)
	for i:=1; i<n; i++ {
		var a,b,c int
		scan(&a,&b,&c)
		tree[a] = append(tree[a], [2]int{b,c})
		tree[b] = append(tree[b], [2]int{a,c})
	}

	ans := int64(0)
	id := 0
	for i:=1; i<=n; i++ {
		for c:=0; c<2; c++ {
			dfs(i,0,c,id)
			ans += int64(cnt[id])*int64(cnt[id]-1)
			id++
		}
	}

	for i:=1; i<=n; i++ {
		a,b := adj[i][0], adj[i][1]
		ans += int64(cnt[a]-1)*int64(cnt[b]-1)
	}

	print(ans, "\n")
	writer.Flush()
	return
}

package main

import (
    "bufio"
    "fmt"
    "os"
)

const (
    N   int = 2e5 + 1
    mod int = 1e9 + 7
)

type pair struct {
    child, wt int
}

var adj [N][]pair
var dp [N][2][2]int64
var ans int64

func dfs(node, par, col int) {
    for _, v := range adj[node] {
        if v.child == par {
            continue
        }
        dfs(v.child, node, v.wt)
        ans += dp[v.child][v.wt][v.wt ^ 1] + 2 * dp[v.child][v.wt][v.wt]
        ans += 2 * dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt]
        ans += dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt ^ 1]
        ans += dp[node][v.wt][v.wt ^ 1] * dp[v.child][v.wt][v.wt]
        ans += dp[node][v.wt ^ 1][v.wt ^ 1] * dp[v.child][v.wt][v.wt]
        for i := 0; i < 2; i++ {
            dp[node][v.wt][i] += dp[v.child][v.wt][i]
        }
    }
    dp[node][col][col ^ 1] += dp[node][col ^ 1][col ^ 1]
    dp[node][col ^ 1][col] = 0
    dp[node][col ^ 1][col ^ 1] = 0
    dp[node][col][col]++
}

func main() {
    in := bufio.NewReader(os.Stdin)
    var n int
    fmt.Fscan(in, &n)
    for i := 1; i < n; i++ {
        var u, v, c int
        fmt.Fscan(in, &u, &v, &c)
        adj[u] = append(adj[u], pair{v, c})
        adj[v] = append(adj[v], pair{u, c})
    }
    dfs(1, 0, 0)
    fmt.Println(ans)
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func solve(j Jam) {
	n := uint32(j.Int())
	zeroClusters, oneClusters := UnionFindNew(n), UnionFindNew(n)
	for l := uint32(1); l < n; l++ {
		x, y, c := uint32(j.Int())-1, uint32(j.Int()-1), j.Int() > 0
		if c {
			oneClusters.Union(x, y)
		} else {
			zeroClusters.Union(x, y)
		}
	}
	validPairs := int64(0)
	countedZeroComponents, countedOneComponents := make(map[uint32]bool, n), make(map[uint32]bool, n)
	for v := uint32(0); v < n; v++ {
		zeroClusterSize, oneClusterSize := zeroClusters.Size(v), oneClusters.Size(v)
		zeroClusterRoot, oneClusterRoot := zeroClusters.Find(v), oneClusters.Find(v)
		if zeroClusterSize > 1 && !countedZeroComponents[zeroClusterRoot] {
			validPairs += int64(zeroClusterSize) * int64(zeroClusterSize-1)
			countedZeroComponents[zeroClusterRoot] = true
		}
		if oneClusterSize > 1 && !countedOneComponents[oneClusterRoot] {
			validPairs += int64(oneClusterSize) * int64(oneClusterSize-1)
			countedOneComponents[oneClusterRoot] = true
		}
		if zeroClusterSize > 1 && oneClusterSize > 1 {
			validPairs += int64(zeroClusterSize-1) * int64(oneClusterSize-1)
		}
	}
	j.P("%d\n", validPairs)
}

func main() {
	jam, closeFunc := JamNew()
	defer closeFunc()
	solve(jam)
}

type Jam interface {
	Scanner() *bufio.Scanner
	Writer() *bufio.Writer
	Close()

	Str() string
	Int() int64
	Float() float64

	P(format string, values ...interface{})
	PF(format string, values ...interface{})
}

func JamNew() (Jam, func()) {
	if len(os.Args) > 1 {
		panic("running with input file path is not supported")
	}

	var scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 0, 1024*1024), 1024*1024)

	var writer = bufio.NewWriter(os.Stdout)
	jam := &jam{scanner, writer}
	return jam, jam.Close
}

type jam struct {
	sc *bufio.Scanner
	wr *bufio.Writer
}

func (j *jam) Close() {
	if err := j.wr.Flush(); err != nil {
		panic(err)
	}
}

func (j *jam) Scanner() *bufio.Scanner {
	return j.sc
}

func (j *jam) Writer() *bufio.Writer {
	return j.wr
}

func (j *jam) Str() string {
	if !j.sc.Scan() {
		panic("failed to scan next token")
	}

	return j.sc.Text()
}

func (j *jam) Int() int64 {
	if !j.sc.Scan() {
		panic("failed to scan next token")
	}

	res, err := strconv.ParseInt(j.sc.Text(), 10, 64)
	if err != nil {
		panic(err)
	}

	return res
}

func (j *jam) Float() float64 {
	j.sc.Scan()
	res, err := strconv.ParseFloat(j.sc.Text(), 64)
	if err != nil {
		panic(err)
	}
	return res
}

func (j *jam) P(format string, values ...interface{}) {
	_, err := fmt.Fprintf(j.wr, format, values...)
	if err != nil {
		panic(err)
	}
}

func (j *jam) PF(format string, values ...interface{}) {
	_, err := fmt.Fprintf(j.wr, format, values...)
	if err != nil {
		panic(err)
	}
	if err = j.wr.Flush(); err != nil {
		panic(err)
	}
}

type UnionFind struct {
	parent []uint32
	size   []uint32
	count  uint32
}

func UnionFindNew(count uint32) *UnionFind {
	parent := make([]uint32, count, count)
	size := make([]uint32, count, count)
	lim := count
	for i := uint32(0); i < lim; i++ {
		parent[i], size[i] = i, 1
	}
	return &UnionFind{parent, size, lim}
}

func (ufp *UnionFind) Reset() {
	lim := uint32(len(ufp.parent))
	for i := uint32(0); i < lim; i++ {
		ufp.parent[i], ufp.size[i] = i, 1
	}
	ufp.count = lim
}

func (ufp *UnionFind) validate(p uint32) {
	n := uint32(len(ufp.parent))
	if p >= n {
		panic(fmt.Sprintf("index %d is not between 0 and %d", p, n - 1))
	}
}

func (ufp *UnionFind) Count() uint32 {
	return ufp.count
}

func (ufp *UnionFind) Find(p uint32) uint32 {
	ufp.validate(p)

	root := p
	for root != ufp.parent[root] {
		root = ufp.parent[root]
	}
	for p != root {
		newp := ufp.parent[p]
		ufp.parent[p] = root
		p = newp
	}

	return root
}

func (ufp *UnionFind) Size(p uint32) uint32 {
	return ufp.size[ufp.Find(p)]
}

func (ufp *UnionFind) Connected(p, q uint32) bool {
	return ufp.Find(p) == ufp.Find(q)
}

func (ufp *UnionFind) Union(p, q uint32) {
	rootP := ufp.Find(p)
	rootQ := ufp.Find(q)

	if rootP == rootQ {
		return
	}

	if ufp.size[rootP] < ufp.size[rootQ] {
		ufp.parent[rootP] = rootQ
		ufp.size[rootQ] += ufp.size[rootP]
	} else {
		ufp.parent[rootQ] = rootP
		ufp.size[rootP] += ufp.size[rootQ]
	}

	ufp.count -= 1
}

package main

import (
    "bufio"
    "fmt"
    "os"
)

const (
    N   int = 2e5
    mod int = 1e9 + 7
)

type pair struct {
    child, wt int
}

var adj [N][]pair
var dp [N][2][2]int64
var ans int64

func dfs(node, par, col int) {
    for _, v := range adj[node] {
        if v.child == par {
            continue
        }
        dfs(v.child, node, v.wt)
        ans += dp[v.child][v.wt][v.wt ^ 1] + 2 * dp[v.child][v.wt][v.wt]
        ans += 2 * dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt]
        ans += dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt ^ 1]
        ans += dp[node][v.wt ^ 1][v.wt ^ 1] * dp[v.child][v.wt][v.wt]
        for i := 0; i < 2; i++ {
            dp[node][v.wt][i] += dp[v.child][v.wt][i]
        }
    }
    dp[node][col][col ^ 1] += dp[node][col ^ 1][col ^ 1]
    dp[node][col ^ 1][col] = 0
    dp[node][col ^ 1][col ^ 1] = 0
    dp[node][col][col]++
}

func main() {
    in := bufio.NewReader(os.Stdin)
    var n int
    fmt.Fscan(in, &n)
    for i := 1; i < n; i++ {
        var u, v, c int
        fmt.Fscan(in, &u, &v, &c)
        adj[u] = append(adj[u], pair{v, c})
        adj[v] = append(adj[v], pair{u, c})
    }
    dfs(1, 0, 0)
    fmt.Println(ans)
}

package main

import (
    "bufio"
    "fmt"
    "os"
)

const (
    N   int = 2e5 + 1
    mod int = 1e9 + 7
)

type pair struct {
    child, wt int
}

var adj [N][]pair
var dp [N][2][2]int64
var ans int64

func dfs(node, par, col int) {
    for _, v := range adj[node] {
        if v.child == par {
            continue
        }
        dfs(v.child, node, v.wt)
        v.wt = 0
        ans += dp[v.child][v.wt][v.wt ^ 1] + 2 * dp[v.child][v.wt][v.wt]
        ans += 2 * dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt]
        ans += dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt ^ 1]
        ans += dp[node][v.wt ^ 1][v.wt ^ 1] * dp[v.child][v.wt][v.wt]
        for i := 0; i < 2; i++ {
            dp[node][v.wt][i] += dp[v.child][v.wt][i]
        }
        v.wt = 1
        ans += dp[v.child][v.wt][v.wt ^ 1] + 2 * dp[v.child][v.wt][v.wt]
        ans += 2 * dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt]
        ans += dp[node][v.wt][v.wt] * dp[v.child][v.wt][v.wt ^ 1]
        ans += dp[node][v.wt ^ 1][v.wt ^ 1] * dp[v.child][v.wt][v.wt]
        for i := 0; i < 2; i++ {
            dp[node][v.wt][i] += dp[v.child][v.wt][i]
        }
    }
    dp[node][col][col ^ 1] += dp[node][col ^ 1][col ^ 1]
    dp[node][col ^ 1][col] = 0
    dp[node][col ^ 1][col ^ 1] = 0
    dp[node][col][col]++
}

func main() {
    in := bufio.NewReader(os.Stdin)
    var n int
    fmt.Fscan(in, &n)
    for i := 1; i < n; i++ {
        var u, v, c int
        fmt.Fscan(in, &u, &v, &c)
        adj[u] = append(adj[u], pair{v, c})
        adj[v] = append(adj[v], pair{u, c})
    }
    dfs(1, 0, 0)
    fmt.Println(ans)
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	var T int
	var n int
	var s string
	var ans string
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	fmt.Fscan(in, &T)
	for _case := 0; _case < T; _case++ {
		fmt.Fscan(in, &n,  &s)
		ans = ""
		for _, b := range s {
			if (b-'0')&1 == 1 {
				ans += string(b)
				if len(ans) == 2 {
					break
				}
			}
		}
		if len(ans) != 2 {
			ans = "-1"
		}
		fmt.Fprintln(out, ans)
	}
}

package main

import (
	"fmt"
	"bufio"
	"os"
	"strconv"
)

//•*¨*•.¸¸♪I/O•*¨*•.¸¸♪

var (
	sc = bufio.NewScanner(os.Stdin)
	wr = bufio.NewWriter(os.Stdout)
)

func scanInt() int {
	sc.Scan()
	a,_ := strconv.Atoi(sc.Text())
	return a
}

func scanInt64() int64 {
	sc.Scan()
	a,_ := strconv.ParseInt(sc.Text(),10,64)
	return a
}

func scanFloat64() float64 {
	sc.Scan()
	a,_ := strconv.Atoi(sc.Text())
	return float64(a)
}

func scanInts(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ { res[i] = scanInt() }
	return res
}

func scanText() string {
	sc.Scan()
	return sc.Text()
}

func printInts(a ...int) {
	for i, e := range a {
		fmt.Fprint(wr, e)
		if i != len(a)-1 { fmt.Fprint(wr, " ") }
	}
	fmt.Fprintln(wr)
	wr.Flush()
}

//•*¨*•.¸¸♪Main•*¨*•.¸¸♪(　-ω-)ノ　(　・ω・)

func main() {
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 10000), 100000000)

	t := scanInt()

	for i := 0; i < t; i++ {
		n := scanInt()
		s := scanText()
		ans := []rune{}
		for j := 0; j < n; j++ {
			num, _ := strconv.Atoi(string(s[j]))
			if num%2 != 1 {
				continue
			}

			ans = append(ans, rune(s[j]))
		}

		if len(ans)%2 == 1 {
			ans = ans[1:]
		}

		if len(ans) == 0 {
			fmt.Println(-1)
			continue
		}

		fmt.Println(string(ans))

	}
}

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var t int
	fmt.Fscanf(reader, "%d\n", &t)
	for i := 0; i < t; i++ {
		var n int
		var s string
		fmt.Fscanf(reader, "%d\n%s\n", &n, &s)
		fmt.Fprintf(writer, "%s\n", makeEbne(s))
	}
}

func makeEbne(s string) string {
	strWr := bytes.NewBufferString("")
	for _, ch := range s {
		d := int(ch) - '0'
		if d%2 != 0 {
			fmt.Fprintf(strWr, "%d", d)
		}
		if len(strWr.String()) == 2 {
			return strWr.String()
		}
	}
	return "-1"
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	solve := func() (ans string) {
		var n int
		var s []byte
		Fscan(in, &n, &s)
		for _, b := range s {

			if (b-'0')&1 == 1 {
				ans += string(b)
				if len(ans) == 2 {
					return
				}
			}
		}

		return "-1"
	}

	var t int
	Fscan(in, &t)
	for _case := 1; _case <= t; _case++ {
		_ans := solve()
		Fprintln(out, _ans)
	}

}

func main() { run(os.Stdin, os.Stdout) }

package main
import (
	"bufio"
	"fmt"
	"os"
)
func main() {
	r := bufio.NewReader(os.Stdin)
	w := bufio.NewWriter(os.Stdout)
	defer w.Flush()

	var t int
	fmt.Fscan(r, &t)
	ans := make([]int, t)
	for i := 0; i < t; i++ {
		var n, j, a int
		var s string
		fmt.Fscan(r, &n, &s)
		for _, c := range s {
			if int(c - '0')%2 != 0 {
				a *= 10
				a += int(c - '0')
				j++
				if j == 2 {
					ans[i] = a
					break
				}
			}
		}
	}
	for _, i := range ans {
		if i == 0 {
			fmt.Fprintln(w, "-1")
		} else {
			fmt.Fprintln(w, i)
		}
	}
}

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var t int
	fmt.Fscanf(reader, "%d\n", &t)
	for i := 0; i < t; i++ {
		var n int
		var s string
		fmt.Fscanf(reader, "%d\n%s\n", &n, &s)
		fmt.Fprintf(writer, "%s\n", makeEbne(s))
	}
}

func makeEbne(s string) string {
	n := len(s)

	if n <= 1 {
		return "-1"
	}

	ds := make([]int, 0, n)
	for _, d := range s {
		ds = append(ds, int(d)-'0')
	}

	if (n > 0) && (ds[n-1]%2) == 0 {
		n--
		ds = ds[:n]
	}

	if n == 0 {
		return "-1"
	}

	sum := 0
	for _, d := range ds {
		sum += d
	}

	skip := -1
	if sum%2 != 0 {
		for i, d := range ds {
			if (d % 2) != 0 {
				skip = i
				break
			}
		}
		if skip == -1 {
			return "-1"
		}
	}

	ret := ""
	strWr := bytes.NewBufferString(ret)
	for i, d := range ds {
		if i == skip {
			continue
		}
		fmt.Fprintf(strWr, "%d", d)
	}

	if len(s) == 0 {
		return "-1"
	}

	return strWr.String()
}

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var t int
	fmt.Fscanf(reader, "%d\n", &t)
	for i := 0; i < t; i++ {
		var n int
		var s string
		fmt.Fscanf(reader, "%d\n%s\n", &n, &s)
		fmt.Fprintf(writer, "%s\n", makeEbne(s))
	}
}

func makeEbne(s string) string {
	n := len(s)

	ds := make([]int, 0, n)
	for _, d := range s {
		ds = append(ds, int(d)-'0')
	}

	for (n > 0) && (ds[n-1]%2 == 0) {
		n--
		ds = ds[:n]
	}

	sum := 0
	for _, d := range ds {
		sum += d
	}

	skip := -1
	if sum%2 != 0 {
		for i, d := range ds {
			if (d % 2) != 0 {
				skip = i
				break
			}
		}
		if skip == -1 || skip == n-1 {
			return "-1"
		}
	}

	ret := ""
	strWr := bytes.NewBufferString(ret)
	for i, d := range ds {
		if i == skip {
			continue
		}
		fmt.Fprintf(strWr, "%d", d)
	}

	if len(strWr.String()) == 0 {
		return "-1"
	}

	return strWr.String()
}

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var t int
	fmt.Fscanf(reader, "%d\n", &t)
	for i := 0; i < t; i++ {
		var n int
		var s string
		fmt.Fscanf(reader, "%d\n%s\n", &n, &s)
		fmt.Fprintf(writer, "%s\n", makeEbne(s))
	}
}

func makeEbne(s string) string {
	n := len(s)

	ds := make([]int, 0, n)
	for _, d := range s {
		ds = append(ds, int(d)-'0')
	}

	for (n > 0) && (ds[n-1]%2 == 0) {
		n--
		ds = ds[:n]
	}

	sum := 0
	for _, d := range ds {
		sum += d
	}

	skip := -1
	if sum%2 != 0 {
		for i, d := range ds {
			if (d % 2) != 0 {
				skip = i
				break
			}
		}
		if skip == -1 {
			return "-1"
		}
	}

	ret := ""
	strWr := bytes.NewBufferString(ret)
	for i, d := range ds {
		if i == skip {
			continue
		}
		fmt.Fprintf(strWr, "%d", d)
	}

	if len(strWr.String()) == 0 {
		return "-1"
	}

	return strWr.String()
}

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var t int
	fmt.Fscanf(reader, "%d\n", &t)
	for i := 0; i < t; i++ {
		var n int
		var s string
		fmt.Fscanf(reader, "%d\n%s\n", &n, &s)
		fmt.Fprintf(writer, "%s\n", makeEbne(s))
	}
}

func makeEbne(s string) string {
	n := len(s)

	ds := make([]int, 0, n)
	for _, d := range s {
		ds = append(ds, int(d)-'0')
	}

	if (n > 0) && (ds[n-1]%2) == 0 {
		n--
		ds = ds[:n]
	}

	if n == 0 {
		return "-1"
	}

	sum := 0
	for _, d := range ds {
		sum += d
	}

	skip := -1
	if sum%2 != 0 {
		for i, d := range ds {
			if (d % 2) != 0 {
				skip = i
				break
			}
		}
		if skip == -1 {
			return "-1"
		}
	}

	ret := ""
	strWr := bytes.NewBufferString(ret)
	for i, d := range ds {
		if i == skip {
			continue
		}
		fmt.Fprintf(strWr, "%d", d)
	}

	if len(strWr.String()) == 0 {
		return "-1"
	}

	return strWr.String()
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

func run(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()

	solve := func() (ans string) {
		var n int
		var s []byte
		Fscan(in, &n, &s)
		for _, b := range s {

			if (b-'0') &1==1 {
				return string(b)
			}
		}

		return "-1"
	}

	var t int
	Fscan(in, &t)
	for _case := 1; _case <= t; _case++ {
		_ans := solve()
		Fprintln(out, _ans)
	}

}

func main() { run(os.Stdin, os.Stdout) }


//361B
package main
import "fmt"

func main() {
	var nn, kk int
	var x[100005]int
	fmt.Scan(&nn, &kk)
	if kk==nn {
		fmt.Println("-1")
	} else {
		x[1]=nn-kk
		for i:=2; i<=nn-kk; i++ {
			x[i]=i-1
		}
		for i:=nn-kk+1; i<=nn; i++ {
			x[i]=i
		}
		fmt.Print(x[1])
		for i:=2; i<=nn; i++ {
			fmt.Print(" ", x[i])
		}
		fmt.Println()
	}
}

// http://acm.timus.ru/problem.aspx?space=1&num=1741
package main

import (
	"fmt"
	"bufio"
	"os"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main () {
	var n, k int

	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	fmt.Fscanln(input, &n, &k)

	if n == k {
		fmt.Println(-1)
		return
	}

	vp := n - k - 1
	fmt.Print(vp + 1)

	for i := 2; i <= n; i++ {
		if vp > 0 {
			fmt.Print(" ", i - 1)
			vp--
		} else {
			fmt.Print(" ", i)
		}
	}

}

// 361B-ahalim,dikai,eric
package main

import (
	"fmt"
)

func main() {
	var n,k,i int
	fmt.Scan(&n,&k)
	if k == n {
		fmt.Println("-1")
	}else{
		for i=1;i<n-k;i++{
			fmt.Print(i+1," ")
		}
		fmt.Print("1 ")

		for i=n-k+1;i<=n;i++{
			fmt.Print(i," ")
		}
		fmt.Println()
	}
}

// 361B
package main

import (
	"fmt"
)

func main() {
	var n, k int
	fmt.Scan(&n, &k)
	if n == k {
		fmt.Print(-1)
		return
	}
	fmt.Printf("%d ", n-k)
	for i := 1; i <= n; i++ {
		if i != n-k {
			fmt.Printf("%d ", i)
		}
	}
}

// 361B-mic
package main

import (
	"fmt"
)

func main() {
	var A [100000]int
	var n, k int
	fmt.Scan(&n, &k)
	for i := 0; i < n; i++ {
		A[i] = i + 1
	}

	for i := 1; i < n; i++ {
		if k > 0 {
			k--
			continue
		}
		if k == 0 {
			if i+1 == n {
				A[0], A[i] = A[i], A[0]
				break
			}
			A[i], A[i+1] = A[i+1], A[i]
			i++
		}
	}
	if k == 1 {
		fmt.Print("-1 ")
	} else {
		for i := 0; i < n; i++ {
			fmt.Print(A[i], " ")
		}
	}
	fmt.Println()
	return
}

// http://acm.timus.ru/problem.aspx?space=1&num=1741
package main

import (
	"fmt"
	"bufio"
	"os"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main () {
	var n, k int

	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	fmt.Fscanln(input, &n, &k)

	if k == 0 || n == k {
		fmt.Println(-1)
		return
	}

	vp := n - k - 1
	fmt.Print(vp + 1)

	for i := 2; i <= n; i++ {
		if vp > 0 {
			fmt.Print(" ", i - 1)
			vp--
		} else {
			fmt.Print(" ", i)
		}
	}

}

// 361B-ahalim,dikai,eric
package main

import (
	"fmt"
)

func main() {
	var n,k,i int
	fmt.Scan(&n,&k)
	if k == n {
		fmt.Println("-1")
	}else{
		for i=1;i<n-k;i++{
			fmt.Print(i+1," ")
			fmt.Print("1 ")
		}
		for i=(n-k)+1;i<=n;i++{
			fmt.Print(i," ")
		}
		fmt.Println()

	}
}


package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
)

var reader io.Reader
var scanner *bufio.Scanner

func Init(io io.Reader, max_token_size int) {
	reader = bufio.NewReader(io)
	scanner = bufio.NewScanner(reader)
	// max token size
	scanner.Split(bufio.ScanWords)
	scanner.Buffer([]byte{}, max_token_size)
}

func stderr(v ...interface{}) {
	fmt.Fprintln(os.Stderr, v...)
}

func die(v ...interface{}) {
	fmt.Fprintln(os.Stderr, v...)
	os.Exit(1)
}

func NextInt() int {
	bytes := NextBytes()
	i, err := Atoi(bytes)
	if err != nil {
		die(err)
	}
	return i
}
func NextInt64() int64 {
	bytes := NextBytes()
	i, err := Atoi64(bytes)
	if err != nil {
		die(err)
	}
	return i
}

func NextBytes() []byte {
	if !scanner.Scan() {
		die(scanner.Err())
	}
	bytes := scanner.Bytes()
	copied := make([]byte, len(bytes))
	copy(copied, bytes)
	return copied
}

func Atoi(b []byte) (int, error) {
	neg := false
	if b[0] == '+' {
		b = b[1:]
	} else if b[0] == '-' {
		neg = true
		b = b[1:]
	}
	n := 0
	for _, v := range b {
		if v < '0' || v > '9' {
			return 0, strconv.ErrSyntax
		}
		n = n*10 + int(v-'0')
	}
	if neg {
		return -n, nil
	}
	return n, nil
}

func Atoi64(b []byte) (int64, error) {
	neg := false
	if b[0] == '+' {
		b = b[1:]
	} else if b[0] == '-' {
		neg = true
		b = b[1:]
	}
	var n int64
	for _, v := range b {
		if v < '0' || v > '9' {
			return 0, strconv.ErrSyntax
		}
		n = n*10 + int64(v-'0')
	}
	if neg {
		return -n, nil
	}
	return n, nil
}

func ExtendByteArray(a []byte, size int) []byte {
	if size <= len(a) {
		return a
	} else {
		return append(a, make([]byte, size-len(a))...)
	}
}

func ExtendIntArray(a []int, size int) []int {
	if size <= len(a) {
		return a
	} else {
		return append(a, make([]int, size-len(a))...)
	}
}

func reverseInts(a []int) {
	for l, r := 0, len(a)-1; l < r; l, r = l+1, r-1 {
		a[l], a[r] = a[r], a[l]
	}
}

func unique(a []int) int {
	newLen := 0
	n := len(a)
	for i := 0; i < n; i++ {
		if newLen == 0 || a[i] != a[newLen-1] {
			a[newLen] = a[i]
			newLen++
		}
	}
	return newLen
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	inf := os.Stdin
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	// inf, err := os.Open("a.in")
	// if err != nil {
	// 	die(err)
	// }
	// out, err := os.Create("a.out")
	// if err != nil {
	// 	die(err)
	// }
	// defer out.Close()
	Init(inf, 1000010)

	n, m := NextInt(), NextInt()
	s := make([][]byte, n)
	was := make([][]bool, n)

	rowGood, colGood := make([]bool, n), make([]bool, m)
	badRows, badCols := n, m

	for i := 0; i < n; i++ {
		s[i] = NextBytes()
		was[i] = make([]bool, m)
		for j := 0; j < m; j++ {
			if s[i][j] == '#' {
				if !rowGood[i] {
					badRows--
				}
				rowGood[i] = true
				if !colGood[j] {
					badCols--
				}
				colGood[j] = true
			}
		}
	}

	if badCols > 0 && badRows == 0 || badCols == 0 && badRows > 0 {
		fmt.Fprintln(out, -1)
		return
	}

	for i := 0; i < n; i++ {
		if !rowGood[i] {
			continue
		}
		start, end := -1, -1
		cnt := 0
		for j := 0; j < m; j++ {
			if s[i][j] == '#' {
				if start == -1 {
					start = j
				}
				end = j
				cnt++
			}
		}
		if start == -1 || end-start+1 != cnt {
			fmt.Fprintln(out, -1)
			return
		}
	}

	for i := 0; i < m; i++ {
		if !colGood[i] {
			continue
		}
		start, end := -1, -1
		cnt := 0
		for j := 0; j < n; j++ {
			if s[j][i] == '#' {
				if start == -1 {
					start = j
				}
				end = j
				cnt++
			}
		}
		if start == -1 || end-start+1 != cnt {
			fmt.Fprintln(out, -1)
			return
		}
	}

	steps := [4][2]int{
		{0, -1},
		{-1, 0},
		{0, 1},
		{1, 0},
	}

	var dfs func(i, j int)
	dfs = func(i, j int) {
		was[i][j] = true
		for k := 0; k < 4; k++ {
			di, dj := steps[k][0], steps[k][1]
			ni, nj := i+di, j+dj
			if ni < 0 || ni == n || nj < 0 || nj == m {
				continue
			}
			if !was[ni][nj] && s[ni][nj] == '#' {
				dfs(ni, nj)
			}
		}
	}

	res := 0
	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if !was[i][j] && s[i][j] == '#' {
				dfs(i, j)
				res++
			}
		}
	}
	fmt.Fprintln(out, res)

}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func readInt(bytes []byte, from int, val *int) int {
	i := from
	sign := 1
	if bytes[i] == '-' {
		sign = -1
		i++
	}
	tmp := 0
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + int(bytes[i]-'0')
		i++
	}
	*val = tmp * sign
	return i
}

func readNum(reader *bufio.Reader) (a int) {
	bs, _ := reader.ReadBytes('\n')
	readInt(bs, 0, &a)
	return
}

func readTwoNums(reader *bufio.Reader) (a int, b int) {
	res := readNNums(reader, 2)
	a, b = res[0], res[1]
	return
}

func readThreeNums(reader *bufio.Reader) (a int, b int, c int) {
	res := readNNums(reader, 3)
	a, b, c = res[0], res[1], res[2]
	return
}

func readNNums(reader *bufio.Reader, n int) []int {
	res := make([]int, n)
	x := 0
	bs, _ := reader.ReadBytes('\n')
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
	return res
}

func readUint64(bytes []byte, from int, val *uint64) int {
	i := from

	var tmp uint64
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + uint64(bytes[i]-'0')
		i++
	}
	*val = tmp

	return i
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	n, m := readTwoNums(reader)

	grid := make([]string, n)
	for i := 0; i < n; i++ {
		grid[i], _ = reader.ReadString('\n')
		grid[i] = grid[i][:m]
	}

	fmt.Println(solve(n, m, grid))
}

var dd = []int{-1, 0, 1, 0, -1}

func solve(n, m int, grid []string) int {
	col := make([]bool, m)

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' {
				// black
				if i > 0 && grid[i-1][j] == '.' {
					// white
					if col[j] {
						// has another black cell on top of white
						return -1
					}
				}
				col[j] = true
			}
		}
	}

	row := make([]bool, n)

	for j := 0; j < m; j++ {
		for i := 0; i < n; i++ {
			if grid[i][j] == '#' {
				if j > 0 && grid[i][j-1] == '.' {
					if row[i] {
						return -1
					}
				}
				row[i] = true
			}
		}
	}

	var c1, c2 int

	for j := 0; j < m; j++ {
		if col[j] {
			c1++
		}
	}

	for i := 0; i < n; i++ {
		if row[i] {
			c2++
		}
	}

	if c1 > 0 && c1 < m && c2 == n {
		return -1
	}

	if c2 > 0 && c2 < n && c1 == m {
		return -1
	}

	// safe

	vis := make([][]bool, n)
	for i := 0; i < n; i++ {
		vis[i] = make([]bool, m)
	}

	var dfs func(x, y int)

	dfs = func(x, y int) {
		for k := 0; k < 4; k++ {
			u, v := x+dd[k], y+dd[k+1]
			if u < 0 || u >= n || v < 0 || v >= m {
				continue
			}
			if grid[u][v] == '#' && !vis[u][v] {
				vis[u][v] = true
				dfs(u, v)
			}
		}
	}

	var cnt int

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' && !vis[i][j] {
				cnt++
				vis[i][j] = true
				dfs(i, j)
			}
		}
	}

	return cnt
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
)

var reader io.Reader
var scanner *bufio.Scanner

func Init(io io.Reader, max_token_size int) {
	reader = bufio.NewReader(io)
	scanner = bufio.NewScanner(reader)
	// max token size
	scanner.Split(bufio.ScanWords)
	scanner.Buffer([]byte{}, max_token_size)
}

func stderr(v ...interface{}) {
	fmt.Fprintln(os.Stderr, v...)
}

func die(v ...interface{}) {
	fmt.Fprintln(os.Stderr, v...)
	os.Exit(1)
}

func NextInt() int {
	bytes := NextBytes()
	i, err := Atoi(bytes)
	if err != nil {
		die(err)
	}
	return i
}
func NextInt64() int64 {
	bytes := NextBytes()
	i, err := Atoi64(bytes)
	if err != nil {
		die(err)
	}
	return i
}

func NextBytes() []byte {
	if !scanner.Scan() {
		die(scanner.Err())
	}
	bytes := scanner.Bytes()
	copied := make([]byte, len(bytes))
	copy(copied, bytes)
	return copied
}

func Atoi(b []byte) (int, error) {
	neg := false
	if b[0] == '+' {
		b = b[1:]
	} else if b[0] == '-' {
		neg = true
		b = b[1:]
	}
	n := 0
	for _, v := range b {
		if v < '0' || v > '9' {
			return 0, strconv.ErrSyntax
		}
		n = n*10 + int(v-'0')
	}
	if neg {
		return -n, nil
	}
	return n, nil
}

func Atoi64(b []byte) (int64, error) {
	neg := false
	if b[0] == '+' {
		b = b[1:]
	} else if b[0] == '-' {
		neg = true
		b = b[1:]
	}
	var n int64
	for _, v := range b {
		if v < '0' || v > '9' {
			return 0, strconv.ErrSyntax
		}
		n = n*10 + int64(v-'0')
	}
	if neg {
		return -n, nil
	}
	return n, nil
}

func ExtendByteArray(a []byte, size int) []byte {
	if size <= len(a) {
		return a
	} else {
		return append(a, make([]byte, size-len(a))...)
	}
}

func ExtendIntArray(a []int, size int) []int {
	if size <= len(a) {
		return a
	} else {
		return append(a, make([]int, size-len(a))...)
	}
}

func reverseInts(a []int) {
	for l, r := 0, len(a)-1; l < r; l, r = l+1, r-1 {
		a[l], a[r] = a[r], a[l]
	}
}

func unique(a []int) int {
	newLen := 0
	n := len(a)
	for i := 0; i < n; i++ {
		if newLen == 0 || a[i] != a[newLen-1] {
			a[newLen] = a[i]
			newLen++
		}
	}
	return newLen
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	inf := os.Stdin
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	// inf, err := os.Open("a.in")
	// if err != nil {
	// 	die(err)
	// }
	// out, err := os.Create("a.out")
	// if err != nil {
	// 	die(err)
	// }
	// defer out.Close()
	Init(inf, 1000010)

	n, m := NextInt(), NextInt()
	s := make([][]byte, n)
	was := make([][]bool, n)

	minrow, mincol, maxrow, maxcol := n, m, -1, -1

	for i := 0; i < n; i++ {
		s[i] = NextBytes()
		was[i] = make([]bool, m)
		for j := 0; j < m; j++ {
			if s[i][j] == '#' {
				minrow = min(minrow, i)
				mincol = min(mincol, j)
				maxrow = max(maxrow, i)
				maxcol = max(maxcol, j)
			}
		}
	}

	if minrow == n {
		fmt.Fprintln(out, 0)
		return
	}

	for i := minrow; i <= maxrow; i++ {
		s[i] = s[i][mincol : maxcol+1]
	}
	s = s[minrow : maxrow+1]
	newm := maxcol - mincol + 1
	newn := maxrow - minrow + 1

	if newm != m && newn == n || newm == m && newn != n {
		fmt.Fprintln(out, -1)
		return
	}
	n, m = newn, newm

	// stderr(mincol, maxcol)
	// stderr(n, m)
	// for i := 0; i < n; i++ {
	// 	stderr(string(s[i]))
	// }

	for i := 0; i < n; i++ {
		start, end := -1, -1
		cnt := 0
		for j := 0; j < m; j++ {
			if s[i][j] == '#' {
				if start == -1 {
					start = j
				}
				end = j
				cnt++
			}
		}
		if start == -1 || end-start+1 != cnt {
			fmt.Fprintln(out, -1)
			return
		}
	}

	for i := 0; i < m; i++ {
		start, end := -1, -1
		cnt := 0
		for j := 0; j < n; j++ {
			if s[j][i] == '#' {
				if start == -1 {
					start = j
				}
				end = j
				cnt++
			}
		}
		if start == -1 || end-start+1 != cnt {
			fmt.Fprintln(out, -1)
			return
		}
	}

	steps := [4][2]int{
		{0, -1},
		{-1, 0},
		{0, 1},
		{1, 0},
	}

	var dfs func(i, j int)
	dfs = func(i, j int) {
		was[i][j] = true
		for k := 0; k < 4; k++ {
			di, dj := steps[k][0], steps[k][1]
			ni, nj := i+di, j+dj
			if ni < 0 || ni == n || nj < 0 || nj == m {
				continue
			}
			if !was[ni][nj] && s[ni][nj] == '#' {
				dfs(ni, nj)
			}
		}
	}

	res := 0
	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if !was[i][j] && s[i][j] == '#' {
				dfs(i, j)
				res++
			}
		}
	}
	fmt.Fprintln(out, res)

}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func readInt(bytes []byte, from int, val *int) int {
	i := from
	sign := 1
	if bytes[i] == '-' {
		sign = -1
		i++
	}
	tmp := 0
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + int(bytes[i]-'0')
		i++
	}
	*val = tmp * sign
	return i
}

func readNum(reader *bufio.Reader) (a int) {
	bs, _ := reader.ReadBytes('\n')
	readInt(bs, 0, &a)
	return
}

func readTwoNums(reader *bufio.Reader) (a int, b int) {
	res := readNNums(reader, 2)
	a, b = res[0], res[1]
	return
}

func readThreeNums(reader *bufio.Reader) (a int, b int, c int) {
	res := readNNums(reader, 3)
	a, b, c = res[0], res[1], res[2]
	return
}

func readNNums(reader *bufio.Reader, n int) []int {
	res := make([]int, n)
	x := 0
	bs, _ := reader.ReadBytes('\n')
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
	return res
}

func readUint64(bytes []byte, from int, val *uint64) int {
	i := from

	var tmp uint64
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + uint64(bytes[i]-'0')
		i++
	}
	*val = tmp

	return i
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	n, m := readTwoNums(reader)

	grid := make([]string, n)
	for i := 0; i < n; i++ {
		grid[i], _ = reader.ReadString('\n')
		grid[i] = grid[i][:m]
	}

	fmt.Println(solve(n, m, grid))
}

var dd = []int{-1, 0, 1, 0, -1}

func solve(n, m int, grid []string) int {
	col := make([]bool, m)

	var black int

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' {
				black++
				// black
				if i > 0 && grid[i-1][j] == '.' {
					// white
					if col[j] {
						// has another black cell on top of white
						return -1
					}
				}
				col[j] = true
			}
		}
	}

	if black == 0 {
		return 0
	}

	for j := 0; j < m; j++ {
		if !col[j] {
			return -1
		}
	}

	row := make([]bool, n)

	for j := 0; j < m; j++ {
		for i := 0; i < n; i++ {
			if grid[i][j] == '#' {
				if j > 0 && grid[i][j-1] == '.' {
					if row[i] {
						return -1
					}
				}
				row[i] = true
			}
		}
	}

	for i := 0; i < n; i++ {
		if !row[i] {
			return -1
		}
	}

	// safe

	vis := make([][]bool, n)
	for i := 0; i < n; i++ {
		vis[i] = make([]bool, m)
	}

	var dfs func(x, y int)

	dfs = func(x, y int) {
		for k := 0; k < 4; k++ {
			u, v := x+dd[k], y+dd[k+1]
			if u < 0 || u >= n || v < 0 || v >= m {
				continue
			}
			if grid[u][v] == '#' && !vis[u][v] {
				vis[u][v] = true
				dfs(u, v)
			}
		}
	}

	var cnt int

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' && !vis[i][j] {
				cnt++
				vis[i][j] = true
				dfs(i, j)
			}
		}
	}

	return cnt
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func readInt(bytes []byte, from int, val *int) int {
	i := from
	sign := 1
	if bytes[i] == '-' {
		sign = -1
		i++
	}
	tmp := 0
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + int(bytes[i]-'0')
		i++
	}
	*val = tmp * sign
	return i
}

func readNum(reader *bufio.Reader) (a int) {
	bs, _ := reader.ReadBytes('\n')
	readInt(bs, 0, &a)
	return
}

func readTwoNums(reader *bufio.Reader) (a int, b int) {
	res := readNNums(reader, 2)
	a, b = res[0], res[1]
	return
}

func readThreeNums(reader *bufio.Reader) (a int, b int, c int) {
	res := readNNums(reader, 3)
	a, b, c = res[0], res[1], res[2]
	return
}

func readNNums(reader *bufio.Reader, n int) []int {
	res := make([]int, n)
	x := 0
	bs, _ := reader.ReadBytes('\n')
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
	return res
}

func readUint64(bytes []byte, from int, val *uint64) int {
	i := from

	var tmp uint64
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + uint64(bytes[i]-'0')
		i++
	}
	*val = tmp

	return i
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	n, m := readTwoNums(reader)

	grid := make([]string, n)
	for i := 0; i < n; i++ {
		grid[i], _ = reader.ReadString('\n')
		grid[i] = grid[i][:m]
	}

	fmt.Println(solve(n, m, grid))
}

var dd = []int{-1, 0, 1, 0, -1}

func solve(n, m int, grid []string) int {
	col := make([]bool, m)

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' {
				// black
				if i > 0 && grid[i-1][j] == '.' {
					// white
					if col[j] {
						// has another black cell on top of white
						return -1
					}
				}
				col[j] = true
			}
		}
	}

	row := make([]bool, n)

	for j := 0; j < m; j++ {
		for i := 0; i < n; i++ {
			if grid[i][j] == '#' {
				if j > 0 && grid[i][j-1] == '.' {
					if row[i] {
						return -1
					}
				}
				row[i] = true
			}
		}
	}

	var c1, c2 int

	for j := 0; j < m; j++ {
		if !col[j] {
			c1++
		}
	}

	for i := 0; i < n; i++ {
		if !row[i] {
			c2++
		}
	}

	if c1 > 0 && c1 < m && c2 == n {
		return -1
	}

	if c2 > 0 && c2 < n && c1 == m {
		return -1
	}

	// safe

	vis := make([][]bool, n)
	for i := 0; i < n; i++ {
		vis[i] = make([]bool, m)
	}

	var dfs func(x, y int)

	dfs = func(x, y int) {
		for k := 0; k < 4; k++ {
			u, v := x+dd[k], y+dd[k+1]
			if u < 0 || u >= n || v < 0 || v >= m {
				continue
			}
			if grid[u][v] == '#' && !vis[u][v] {
				vis[u][v] = true
				dfs(u, v)
			}
		}
	}

	var cnt int

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' && !vis[i][j] {
				cnt++
				vis[i][j] = true
				dfs(i, j)
			}
		}
	}

	return cnt
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func readInt(bytes []byte, from int, val *int) int {
	i := from
	sign := 1
	if bytes[i] == '-' {
		sign = -1
		i++
	}
	tmp := 0
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + int(bytes[i]-'0')
		i++
	}
	*val = tmp * sign
	return i
}

func readNum(reader *bufio.Reader) (a int) {
	bs, _ := reader.ReadBytes('\n')
	readInt(bs, 0, &a)
	return
}

func readTwoNums(reader *bufio.Reader) (a int, b int) {
	res := readNNums(reader, 2)
	a, b = res[0], res[1]
	return
}

func readThreeNums(reader *bufio.Reader) (a int, b int, c int) {
	res := readNNums(reader, 3)
	a, b, c = res[0], res[1], res[2]
	return
}

func readNNums(reader *bufio.Reader, n int) []int {
	res := make([]int, n)
	x := 0
	bs, _ := reader.ReadBytes('\n')
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
	return res
}

func readUint64(bytes []byte, from int, val *uint64) int {
	i := from

	var tmp uint64
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + uint64(bytes[i]-'0')
		i++
	}
	*val = tmp

	return i
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	n, m := readTwoNums(reader)

	grid := make([]string, n)
	for i := 0; i < n; i++ {
		grid[i], _ = reader.ReadString('\n')
		grid[i] = grid[i][:m]
	}

	fmt.Println(solve(n, m, grid))
}

var dd = []int{-1, 0, 1, 0, -1}

func solve(n, m int, grid []string) int {
	col := make([]bool, m)

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' {
				// black
				if i > 0 && grid[i-1][j] == '.' {
					// white
					if col[j] {
						// has another black cell on top of white
						return -1
					}
				}
				col[j] = true
			}
		}
	}

	row := make([]bool, n)

	for j := 0; j < m; j++ {
		for i := 0; i < n; i++ {
			if grid[i][j] == '#' {
				if j > 0 && grid[i][j-1] == '.' {
					if row[i] {
						return -1
					}
				}
				row[i] = true
			}
		}
	}

	// safe

	vis := make([][]bool, n)
	for i := 0; i < n; i++ {
		vis[i] = make([]bool, m)
	}

	var dfs func(x, y int)

	dfs = func(x, y int) {
		for k := 0; k < 4; k++ {
			u, v := x+dd[k], y+dd[k+1]
			if u < 0 || u >= n || v < 0 || v >= m {
				continue
			}
			if grid[u][v] == '#' && !vis[u][v] {
				vis[u][v] = true
				dfs(u, v)
			}
		}
	}

	var cnt int

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' && !vis[i][j] {
				cnt++
				vis[i][j] = true
				dfs(i, j)
			}
		}
	}

	return cnt
}

package main

import (
	"bufio"
	"fmt"
	"os"
)

func readInt(bytes []byte, from int, val *int) int {
	i := from
	sign := 1
	if bytes[i] == '-' {
		sign = -1
		i++
	}
	tmp := 0
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + int(bytes[i]-'0')
		i++
	}
	*val = tmp * sign
	return i
}

func readNum(reader *bufio.Reader) (a int) {
	bs, _ := reader.ReadBytes('\n')
	readInt(bs, 0, &a)
	return
}

func readTwoNums(reader *bufio.Reader) (a int, b int) {
	res := readNNums(reader, 2)
	a, b = res[0], res[1]
	return
}

func readThreeNums(reader *bufio.Reader) (a int, b int, c int) {
	res := readNNums(reader, 3)
	a, b, c = res[0], res[1], res[2]
	return
}

func readNNums(reader *bufio.Reader, n int) []int {
	res := make([]int, n)
	x := 0
	bs, _ := reader.ReadBytes('\n')
	for i := 0; i < n; i++ {
		for x < len(bs) && (bs[x] < '0' || bs[x] > '9') && bs[x] != '-' {
			x++
		}
		x = readInt(bs, x, &res[i])
	}
	return res
}

func readUint64(bytes []byte, from int, val *uint64) int {
	i := from

	var tmp uint64
	for i < len(bytes) && bytes[i] >= '0' && bytes[i] <= '9' {
		tmp = tmp*10 + uint64(bytes[i]-'0')
		i++
	}
	*val = tmp

	return i
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	n, m := readTwoNums(reader)

	grid := make([]string, n)
	for i := 0; i < n; i++ {
		grid[i], _ = reader.ReadString('\n')
		grid[i] = grid[i][:m]
	}

	fmt.Println(solve(n, m, grid))
}

var dd = []int{-1, 0, 1, 0, -1}

func solve(n, m int, grid []string) int {
	col := make([]bool, m)

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' {
				// black
				if i > 0 && grid[i-1][j] == '.' {
					// white
					if col[j] {
						// has another black cell on top of white
						return -1
					}
				}
				col[j] = true
			}
		}
	}

	for j := 0; j < m; j++ {
		if !col[j] {
			return -1
		}
	}

	row := make([]bool, n)

	for j := 0; j < m; j++ {
		for i := 0; i < n; i++ {
			if grid[i][j] == '#' {
				if j > 0 && grid[i][j-1] == '.' {
					if row[i] {
						return -1
					}
				}
				row[i] = true
			}
		}
	}

	for i := 0; i < n; i++ {
		if !row[i] {
			return -1
		}
	}

	// safe

	vis := make([][]bool, n)
	for i := 0; i < n; i++ {
		vis[i] = make([]bool, m)
	}

	var dfs func(x, y int)

	dfs = func(x, y int) {
		for k := 0; k < 4; k++ {
			u, v := x+dd[k], y+dd[k+1]
			if u < 0 || u >= n || v < 0 || v >= m {
				continue
			}
			if grid[u][v] == '#' && !vis[u][v] {
				vis[u][v] = true
				dfs(u, v)
			}
		}
	}

	var cnt int

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '#' && !vis[i][j] {
				cnt++
				vis[i][j] = true
				dfs(i, j)
			}
		}
	}

	return cnt
}