/*可以把一个图拆分成两个图。一个统计行,另一个统计列。如果一行连续,则将该连续块打上一个相同的标号,否则,标号加1,该部分的处理有点麻烦。这两个图的坐标如果有相等的部分,就在此连一条边.也是点拆分的建图方法,自身条件匹配,很经典的题。*/
#include <stdio.h>
#include <cstring>
int r[5][5];
int c[5][5];
char map[5][5];
char op[5];
int g[20][20];
bool vis[20];
int match[20];
int n,a,b;
int find(int x)
{
for(int i=1; i<=b; i++)
{
if(!vis[i]&&g[x][i])
{
vis[i]=true;
if(find(match[i])||match[i]==-1)
{
match[i]=x;
return 1;
}
}
}
return 0;
}
int main()
{
while(scanf("%d",&n)==1&&n)
{
memset(r,0,sizeof(r));
memset(c,0,sizeof(c));
memset(match,-1,sizeof(match));
memset(g,0,sizeof(g));
for(int i=0; i<n; i++)
{
scanf("%s",op);
for(int j=0; j<n; j++)
map[i][j]=op[j];
}
a=0;
bool ret;
for(int i=0; i<n; i++) //遇到末尾和X都要a++,则将这两步都不进行a++。放到简单的那个步骤‘.’上,避免分类过多讨论
{
ret=true;
for(int j=0; j<n; j++)
{
if(map[i][j]=='.')
{
if(ret)
a++;
r[i][j]=a;
ret=false;
}
else
{
ret=true;
r[i][j]=-1;
}
}
}
b=0;
for(int j=0; j<n; j++)
{
ret=true;
for(int i=0; i<n; i++)
{
if(map[i][j]=='.')
{
if(ret)
b++;
c[i][j]=b;
ret=false;
}
else
{
ret=true;
c[i][j]=-1;
}
}
}
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
if(r[i][j]!=-1&&c[i][j]!=-1)
g[r[i][j]][c[i][j]]=1;
}
int count=0;
for(int i=1; i<=a; i++)
{
memset(vis,false,sizeof(vis));
count+=find(i);
}
printf("%d\n",count);
}
return 0;
}