/*首先bfs搜索所有岛屿,由于子岛屿是不与外海连接的,所以再判断与子岛屿的相邻的水能否到地图边缘*/
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=55;
int T;
int n,m;
char s[N][N];
bool vis[N][N],st[N][N]; //vis用于寻找陆地时判重,st用于判断领海能否到地图边缘时判重
int dx[8]={-1,1,0,0,-1,-1,1,1},dy[8]={0,0,-1,1,-1,1,-1,1};
//判断是否是外海时,需要判断八个方向,而判断陆地只需要上下左右四个方向
void bfs(int x,int y) //找到有多少个岛屿
{
queue<PII> q;
q.push({x,y});
vis[x][y]=true;
while(q.size())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int tx=t.first+dx[i],ty=t.second+dy[i];
if(tx<1 || tx>n || ty<1 || ty>m || vis[tx][ty] || s[tx][ty]!='1') continue;
vis[tx][ty]=true;
q.push({tx,ty});
}
}
}
bool check(int x,int y) //判断是否为子岛屿
{
queue<PII> p;
p.push({x,y});
st[x][y]=true;
while(p.size())
{
auto t=p.front();
p.pop();
if(t.first==1 || t.first==n || t.second==1 || t.second==m) return true;
for(int i=0;i<8;i++)
{
int tx=t.first+dx[i],ty=t.second+dy[i];
if(tx<1 || tx>n || ty<1 || ty>m || st[tx][ty] || s[tx][ty]!='0') continue;
st[tx][ty]=true;
p.push({tx,ty});
}
}
return false;
}
int solve()
{
cin>>n>>m;
memset(vis,false,sizeof vis);
memset(st,false,sizeof st);
for(int i=1;i<=n;i++)
{
cin>>s[i]+1;
}
int ans=0; //陆地数量
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!vis[i][j] && s[i][j]=='1')
{
bfs(i,j);
memcpy(st,vis,sizeof vis);
//非常重要,如果没有这一步,会导致前面一个岛屿将地图边缘的海标记为搜索过,如果地图边缘的海全被标记为搜索过的,那么后面的岛屿将被迫认为是子岛屿,因为它不能找到地图边缘上的海了,而且没有这一步,会导致check函数在判断子岛屿时还需要判断陆地,会导致超时
if(check(i,j)) ans++; //如果不是子岛屿,岛屿数量加一
}
}
}
return ans;
}
int main()
{
cin>>T;
while(T--)
{
cout<<solve()<<endl;
}
return 0;
}