#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
#include<queue>
#include<functional>
#include<numeric>
#include<limits>
#include<map>
#include<bitset>
#include<array>
#include<boost/multi_array.hpp>

namespace utility
{
	template<class T>struct addable;
	template<class T>struct subtractable;
	template<class T>struct multipliable;
	template<class T>struct dividable;
	template<class T,class U> decltype(auto) operator+(T const& lhs, U const& rhs)
	{
		auto x = lhs;
		x += rhs;
		return x;
	}
	template<class T, class U> decltype(auto) operator-(T const& lhs, U const& rhs)
	{
		auto x = lhs;
		x -= rhs;
		return x;
	}
	template<class T, class U> decltype(auto) operator*(T const& lhs, U const& rhs)
	{
		auto x = lhs;
		x *= rhs;
		return x;
	}
	template<class T, class U> decltype(auto) operator/(T const& lhs, U const& rhs)
	{
		auto x = lhs;
		x /= rhs;
		return x;
	}
	template<class T>struct equality_comparable
	{
		 decltype(auto) operator!=(equality_comparable<T>const& rhs)const
		{
			return !(static_cast<T const&>(*this) == static_cast<T const&>(rhs));
		}

	};
	template<class T>struct less_than_comparable
	{
		 decltype(auto)operator<(equality_comparable<T>const& rhs)const
		{
			return static_cast<T const&>(*this) < static_cast<T const&>(rhs);
		}
		 decltype(auto)operator>(T const& rhs)const
		{
			return rhs < *this;
		}
		 decltype(auto)operator<=(T const& rhs)const
		{
			return !(rhs < *this);
		}
		 decltype(auto)operator>=(T const& rhs)const
		{
			return !(*this < rhs);
		}

	};
	template<class T>struct addable
	{
		 decltype(auto) operator+=(addable<T>const& rhs)
		{
			return static_cast<T const&>(*this) += static_cast<T const&>(rhs);
		}
		friend  decltype(auto) operator+(addable<T>const& lhs, addable<T>const& rhs);
	};
	template<class T>struct subtractable
	{
		 decltype(auto) operator-=(subtractable<T>const& rhs)
		{
			return static_cast<T const&>(*this) -= static_cast<T const&>(rhs);
		}

		friend  decltype(auto) operator-(subtractable<T>const& lhs, subtractable<T>const& rhs);
	};
	template<class T>struct multipliable
	{
		 decltype(auto) operator*=(multipliable<T>const& rhs)
		{
			return static_cast<T const&>(*this) *= static_cast<T const&>(rhs);
		}
		friend  decltype(auto) operator*(multipliable<T>const& lhs, multipliable<T>const& rhs);
	};
	template<class T>struct dividable
	{
		 decltype(auto) operator/=(dividable<T>const& rhs)
		{
			return static_cast<T const&>(*this) /= static_cast<T const&>(rhs);
		}
		friend  decltype(auto) operator/(dividable<T>const& lhs, dividable<T>const& rhs);
	};

	struct nullopt_t
	{

	};
	constexpr nullopt_t nullopt{};
	template<class T>class optional:private equality_comparable<optional<T>>
	{
		union
		{
			T val;
			nullopt_t null;
		};
		bool flag;
	public:
		 optional(nullopt_t n = nullopt) : null(), flag(false)
		{

		}

		 T& operator*()
		{
			if (flag)
			{
				return val;
			}
			throw std::invalid_argument("this optional value has not any value");
		}
		 T const& operator*()const
		{
			if (flag)
			{
				return val;
			}
			throw std::invalid_argument("this optional value has not any value");
		}
		 void reset()
		{
			null = nullopt;
			flag = false;
		}
		 operator bool()const
		{
			return flag;
		}
		template<class... Us>void emplace(Us&&... args)
		{
			val = T(std::forward<Us>(args)...);
			flag = true;
		}
		 auto& operator=(T const& v)
		{
			val = v;
			flag = true;
			return *this;
		}
		 auto& operator=(T&& v)
		{
			val = v;
			flag = true;
			return *this;
		}
		 auto& operator=(nullopt_t)
		{
			null = nullopt;
			flag = false;
			return *this;
		}

		 optional(T const& v) :optional()
		{
			*this = v;
		}
		 optional(T&& v) : optional()
		{
			*this = std::move(v);
		}

		 bool operator==(optional const& rhs)const
		{
			return flag&&rhs.flag ? val == rhs.val : flag == rhs.flag;
		}

		optional(optional const&) = default;
		optional(optional&&) = default;
		optional& operator=(optional const&) = default;
		optional& operator=(optional&&) = default;
		~optional() = default;
		
	};
}
namespace math
{
	template<class T>constexpr T pow(T val, std::uint64_t p)
	{
		return p == 0 ? T(1) :
			p == 1 ? val :
			p == 2 ? val*val :
			p % 2 == 0 ? pow(pow(val, p / 2), 2) :
			pow(pow(val, p / 2), 2)*val;
	}
	template<class T,class U>constexpr int ilog(T val, U base)
	{
		T v(1);
		for (int i{};;++i)
		{
			if (val <= v)
			{
				return i;
			}
			v *= base;
		}
	}

	template<std::uint64_t Mod>class mod_number:
		private utility::equality_comparable<mod_number<Mod>>,
		private utility::addable<mod_number<Mod>>,
		private utility::subtractable<mod_number<Mod>>,
		private utility::multipliable<mod_number<Mod>>,
		private utility::dividable<mod_number<Mod>>
	{
		std::uint64_t value;
	public:
		mod_number(std::uint64_t v = 0) :value(v%Mod)
		{

		}
		mod_number(int v) :value(v%Mod)
		{

		}
		mod_number(std::int64_t v) :value(v%Mod)
		{

		}
		mod_number(std::uint32_t v) :value(v%Mod)
		{

		}

		bool operator==(mod_number const& rhs)
		{
			return value == rhs.value;
		}

		auto& operator+=(mod_number const& rhs)
		{
			value += rhs.value;
			value %= Mod;
			return *this;
		}

		auto& operator-=(mod_number const& rhs)
		{
			value += Mod - rhs.value;
			value %= Mod;
			return *this;
		}

		auto& operator*=(mod_number const& rhs)
		{
			value *= rhs.value;
			value %= Mod;
			return *this;
		}

		auto& operator/=(mod_number const& rhs)
		{
			return operator*=(pow(rhs, Mod - 2));
		}

		std::uint64_t const& get()const
		{
			return value;
		}
	};
	constexpr int bitcount(unsigned int x)
	{
		x = (x & 0x55555555) + ((x & 0xAAAAAAAA) >> 1);
		x = (x & 0x33333333) + ((x & 0xCCCCCCCC) >> 2);
		x = (x & 0x0F0F0F0F) + ((x & 0xF0F0F0F0) >> 4);
		x = (x & 0x00FF00FF) + ((x & 0xFF00FF00) >> 8);
		x = (x & 0x0000FFFF) + ((x & 0xFFFF0000) >> 16);
		return static_cast<int>(x);
	}
	constexpr int bitcount(unsigned long long x)
	{
		x = (x & 0b0101010101010101010101010101010101010101010101010101010101010101) + ((x & 0b1010101010101010101010101010101010101010101010101010101010101010) >> 1);
		x = (x & 0b0011001100110011001100110011001100110011001100110011001100110011) + ((x & 0b1100110011001100110011001100110011001100110011001100110011001100) >> 2);
		x = (x & 0b0000111100001111000011110000111100001111000011110000111100001111) + ((x & 0b1111000011110000111100001111000011110000111100001111000011110000) >> 4);
		x = (x & 0b0000000011111111000000001111111100000000111111110000000011111111) + ((x & 0b1111111100000000111111110000000011111111000000001111111100000000) >> 8);
		x = (x & 0b0000000000000000111111111111111100000000000000001111111111111111) + ((x & 0b1111111111111111000000000000000011111111111111110000000000000000) >> 16);
		x = (x & 0b0000000000000000000000000000000011111111111111111111111111111111) + ((x & 0b1111111111111111111111111111111100000000000000000000000000000000) >> 32);
		return static_cast<int>(x);
	}
	constexpr int bitcount(int x)
	{
		return bitcount(static_cast<unsigned int>(x));
	}
	constexpr int bitcount(long long x)
	{
		return bitcount(static_cast<unsigned long long>(x));
	}

	constexpr auto infinity = utility::nullopt;
	template<class T>class infable :
		private utility::addable<T>,
		private utility::subtractable<T>,
		private utility::multipliable<T>,
		private utility::dividable<T>,
		private utility::equality_comparable<T>,
		private utility::less_than_comparable<T>
	{
		utility::optional<T> val;
	public:
		 infable(T v = T()) :val(v)
		{
			
		}
		 infable(utility::nullopt_t) : val()
		{

		}

		 T const& get()const
		{
			return *val;
		}

		 bool operator<(infable<T>const& rhs)const
		{
			if (val&&rhs.val)
			{
				return *val < rhs.get();
			}
			else if (val && !rhs.val)
			{
				return true;
			}
			else
			{
				return false;
			}
		}

		 bool operator==(infable<T>const& rhs)const
		{
			return val == rhs.val;
		}

		 decltype(auto) operator+=(infable<T>const& rhs)
		{
			if (val)
			{
				if (rhs.val)
				{
					*val += rhs.get();
				}
				else
				{
					val = infinity;
				}
			}
			return *this;
		}
		 decltype(auto) operator-=(infable<T>const& rhs)
		{
			if (val)
			{
				if (rhs.val)
				{
					*val -= rhs.get();
				}
				else
				{
					val = infinity;
				}
			}
			return *this;
		}
		 decltype(auto) operator*=(infable<T>const& rhs)
		{
			if (val)
			{
				if (rhs.val)
				{
					*val *= rhs.get();
				}
				else
				{
					val = infinity;
				}
			}
			return *this;
		}
		 decltype(auto) operator/=(infable<T>const& rhs)
		{
			if (val)
			{
				if (rhs.val)
				{
					*val /= rhs.get();
				}
				else
				{
					val = infinity;
				}
			}
			return *this;
		}

	};
}
namespace container
{
	namespace detail
	{
		template<class T, std::size_t Depth>struct tree_array
		{
			std::array<T, (1 << (Depth + 1)) - 1> ar;
			 T& operator()(std::size_t index, std::size_t depth)
			{
				return ar[(1ull << depth) + index - 1];
			}
			 T const& operator()(std::size_t index, std::size_t depth)const
			{
				return ar[(1ull << depth) + index - 1];
			}
		};
	}

	template<class T, std::size_t Size = 1 << 13>class addtree
	{
		std::array<T, 2 * Size - 1> data;
		T get(std::size_t left, std::size_t right, std::size_t i, std::size_t l, std::size_t r)
		{
			if (r <= left || right <= l)
				return T();
			if (left <= l&&r <= right)
			{
				return data[i];
			}
			else
			{
				return 
					get(left, right, 2 * i + 1, l, (l + r) / 2) +
					get(left, right, 2 * i + 2, (l + r) / 2, r);
			}
		}
	public:
		addtree() :data{}
		{

		}
		void change(T const& val, std::size_t index)
		{
			T from = data[index + Size - 1];
			for (std::size_t i = 1, c = math::ilog(Size, 2);i <= Size;(i <<= 1), --c)
			{
				data[i + (index >> c) - 1] -= from;
				data[i + (index >> c) - 1] += val;
			}
		}
		auto begin()const
		{
			return std::next(data.begin(), Size - 1);
		}
		auto end()const
		{
			return data.end();
		}
		T get(std::size_t left, std::size_t right)
		{
			return left > right ? T() : get(left, right + 1, 0, 0, Size);
		}
	};
	template<class T, std::size_t Depth = 13>class minmaxtree
	{
		detail::tree_array<std::pair<T, T>, Depth> data;
		T min(std::size_t left, std::size_t right, std::size_t L, std::size_t R, std::size_t depth)const
		{
			if (right <= L || R <= left)
			{
				return std::numeric_limits<T>::max();
			}
			else if (left <= L&&R <= right)
			{
				return data(L >> (Depth - depth), depth).first;
			}
			else
			{
				return std::min(
					min(left, right, L, (L + R) / 2, depth + 1),
					min(left, right, (L + R) / 2, R, depth + 1));
			}
		}
		T max(std::size_t left, std::size_t right, std::size_t L, std::size_t R, std::size_t depth)const
		{
			if (right <= L || R <= left)
			{
				return std::numeric_limits<T>::min();
			}
			else if (left <= L&&R <= right)
			{
				return data(L >> (Depth - depth), depth).second;
			}
			else
			{
				return std::max(
					max(left, right, L, (L + R) / 2, depth + 1),
					max(left, right, (L + R) / 2, R, depth + 1));
			}
		}
	public:
		void change(T const& val, std::size_t index)
		{
			data(index, Depth).first = val;
			data(index, Depth).second = val;
			for (int i = 1;i <= Depth;++i)
			{
				data(index >> i, Depth - i).first = std::min(
					data((index >> i) << 1, Depth - i + 1).first,
					data(((index >> i) << 1) + 1, Depth - i + 1).first);
				data(index >> i, Depth - i).second = std::max(
					data((index >> i) << 1, Depth - i + 1).second,
					data(((index >> i) << 1) + 1, Depth - i + 1).second);
			}
		}
		T min(std::size_t left, std::size_t right)const
		{
			return right < left ? std::numeric_limits<T>::max() : min(left, right + 1, 0, 1 << Depth, 0);
		}
		T max(std::size_t left, std::size_t right)const
		{
			return right < left ? std::numeric_limits<T>::min() : max(left, right + 1, 0, 1 << Depth, 0);
		}

		minmaxtree() :data{}
		{

		}

	};

	template<class T>using dijkstra_queue = std::priority_queue<T, std::vector<T>, std::greater<>>;
}
namespace algorithm
{
	template<class RandomAccessRange>void sort(RandomAccessRange& range)
	{
		std::sort(std::begin(range), std::end(range));
	}
	template<class T, std::size_t I>void sort(T(&range)[I])
	{
		std::sort(std::begin(range), std::end(range));
	}
	template<class RandomAccessRange,class Compare>void sort(RandomAccessRange& range,Compare&& comp)
	{
		std::sort(std::begin(range), std::end(range), std::forward<Compare>(comp));
	}
	template<class T,std::size_t I, class Compare>void sort(T (&range)[I], Compare&& comp)
	{
		std::sort(std::begin(range), std::end(range), std::forward<Compare>(comp));
	}
}

void Main();
int main()
{
	std::ios::sync_with_stdio(false);
	Main();
}
//ここから頑張る

void Main()
{
	int N;
	std::cin >> N;
	boost::multi_array<char, 2> erea(boost::extents[N][N]);
	std::map<int,std::set<int>> kr;
	std::vector<int> counta(N);
	std::vector<int> countb(N);
	bool f{};
	for (int i{};i < N;++i) 
	{
		for (int j{};j < N;++j)
		{
			char c;
			std::cin >> c;
			if (c == '#')
			{
				kr[i].emplace(j);
				++counta[i];
				++countb[j];
				f = true;
			}
			erea[i][j] = c;
		}
	}
	if (!f)
	{
		std::cout << -1 << std::endl;
		return;
	}
	std::vector<int> maxim(N, -1);
	for (int i{};i < N;++i)
	{
		if (erea[i][i] == '#')
		{
			maxim[i] = counta[i];
			continue;
		}
		if (countb[i] == 0)
		{
			maxim[i] = counta[i] - 1;
		}
		else
		{
			maxim[i] = counta[i];
		}
	}
	std::cout << 2 * N - *std::max_element(maxim.begin(), maxim.end()) - count(countb.begin(), countb.end(), N) << std::endl;
}

Measured memory_bytes: 12288