横坐标 纵坐标 标好编号
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#define cler(arr, val) memset(arr, val, sizeof(arr))
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define IN freopen ("in.txt" , "r" , stdin);
#define OUT freopen ("out.txt" , "w" , stdout);
typedef long long LL;
const int MAXN = 10052;
const int MAXM = 6000010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9;
const double eps= 1e-8;
#define lson l,m, rt<<1
#define rson m+1,r,rt<<1|1
int mp1[155][155],mp2[155][155];
char s[151][151];
const int N=31500;
int use[N];
int linkx[N];
int linky[N];
struct node
{
int to,next;
}edge[MAXN];
int head[N],tol;
void addedge(int u,int v)
{
edge[tol].to=v,edge[tol].next=head[u];
head[u]=tol++;
}
int gn,gm;
int can(int t)
{
int j;
for(j=head[t];~j;j=edge[j].next)
{
int v=edge[j].to;
if(use[v]==0)
{
use[v]=1;//标记
if(linky[v]==0 || can(linky[v]))
{
linky[v]=t;
linkx[t]=v;
return 1;
}
}
}
return 0;
}
int MaxMatch()
{
int i,num;
num=0;
memset(linkx,0,sizeof(linkx));
memset(linky,0,sizeof(linky));
for(i=1;i<gn;i++)
{
memset(use,0,sizeof(use));
if(can(i)) num++;
}
return num;
}
int main()
{
int n;
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
while(cin>>n)
{
memset(mp1,0,sizeof(mp1));
memset(mp2,0,sizeof(mp2));
tol=0;
memset(head,-1,sizeof(head));
for(int i=0;i<n;i++)
scanf("%s",s[i]);
gn=1;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
if(s[i][j]=='.')
mp1[i][j]=gn;
else if(s[i][j]=='X')
gn++;
gn++;
}
gm=1;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
if(s[j][i]=='.')
mp2[j][i]=gm;
else if(s[j][i]=='X')
gm++;
gm++;
}
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
addedge(mp1[i][j],mp2[i][j]);
printf("%d\n",MaxMatch());
}
return 0;
}