#include <iostream>
using namespace std;
int l,c;
char place[45][15];
int graph[600][600];
int used[600];
int link[600];
int hash[500];
int sum;
void side(int v,int w) //与相邻点加边到graph图里
{
int x,y;
x=hash[v*c+w];
if ( v >=1 && place[v-1][w]=='*')
{
y=hash[(v-1)*c+w];
graph[x][y]=1;
}
if (w>=1 && place[v][w-1]=='*' )
{
y=hash[v*c+w-1];
graph[x][y]=1;
}
if (v<=l-2 && place[v+1][w]=='*' )
{
y=hash[(v+1)*c+w];
graph[x][y]=1;
}
if (w<=c-2 && place[v][w+1]=='*' )
{
y=hash[v*c+w+1];
graph[x][y]=1;
}
return ;
}
int can(int t)
{
for (int i=0;i<sum;i++)
if (!used[i] && graph[t][i])
{
used[i]=1;
if (link[i]==-1 || can(link[i]))
{
link[i]=t;
return 1;
}
}
return 0;
}
int solve()
{
int num=0,r=0;
memset(link,-1,sizeof (link));
for (int i=0;i<sum;i++)
{
memset(used,0,sizeof(used));
if (can(i)) num++;
else r++;
}
return num/2+r; //因为两边是一样的点,一定出现一条边(正反向)被算两次,所以num要除以2
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&l,&c);
for (int i=0;i<l;i++)
scanf("%s",&place[i]);
memset(graph,0,sizeof(graph));
sum=0;
for (int i=0;i<l;i++)
for (int j=0;j<c;j++)
if (place[i][j]=='*')
hash[i*c+j]=sum++; //这里hash的技巧很巧妙,把二维的坐标
//转化成一个整数,以作为另一个二维数组的下标hash[i*c+j];
for (int i=0;i<l;i++)
for (int j=0;j<c;j++)
if (place[i][j]=='*') //把所有相邻的点都映射到graph中的一条边,
side(i,j); //最后得到的二分图,其实两边都是一样的点
printf("%d/n",solve());
}
return 0;
}