//#pragma GCC optimize("Ofast,unroll-loops")
//#pragma GCC target("avx2,tune=native")
#include <bits/stdc++.h>
using namespace std;
 
#define ff(i, a, b) for(auto i=(a); i<=(b); ++i)
#define ffr(i, b, a) for(auto i=(b); i>=(a); --i)
#define nl "\n"
#define pb emplace_back
#define sz(s) (int)s.size()
 
typedef long long ll;
typedef vector<int> vi;
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int tt; if(!(cin>>tt)) return 0;
    while(tt--){
        int X,Y,Z; cin>>X>>Y>>Z;
        vector<vector<vector<int>>> a(X, vector<vector<int>>(Y, vector<int>(Z,0)));
        ff(x,0,X-1) ff(y,0,Y-1) ff(z,0,Z-1) cin>>a[x][y][z];
 
        // collect positions that are 1 and map to index
        vector<int> posList; posList.reserve(X*Y*Z);
        vector<int> lin2idx(X*Y*Z, -1);
        int U = 0;
        ff(x,0,X-1) ff(y,0,Y-1) ff(z,0,Z-1){
            if(a[x][y][z]==1){
                int lin = (x*Y + y)*Z + z;
                lin2idx[lin] = U++;
                posList.pb(lin);
            }
        }
        if(U==0){
            cout<<0<<nl;
            continue;
        }
 
        // build 3D prefix sum (1-based)
        vector<vector<vector<int>>> pref(X+1, vector<vector<int>>(Y+1, vector<int>(Z+1,0)));
        for(int x=1;x<=X;x++) for(int y=1;y<=Y;y++) for(int z=1;z<=Z;z++){
            pref[x][y][z] = a[x-1][y-1][z-1]
                + pref[x-1][y][z] + pref[x][y-1][z] + pref[x][y][z-1]
                - pref[x-1][y-1][z] - pref[x-1][y][z-1] - pref[x][y-1][z-1]
                + pref[x-1][y-1][z-1];
        }
        auto sum_box = [&](int x1,int x2,int y1,int y2,int z1,int z2)->int{
            // inputs 1-based inclusive
            int s = pref[x2][y2][z2]
                - pref[x1-1][y2][z2] - pref[x2][y1-1][z2] - pref[x2][y2][z1-1]
                + pref[x1-1][y1-1][z2] + pref[x1-1][y2][z1-1] + pref[x2][y1-1][z1-1]
                - pref[x1-1][y1-1][z1-1];
            return s;
        };
 
        // enumerate all boxes that are fully 1
        struct Box { int cost; vector<int> elems; };
        vector<Box> boxes;
        boxes.reserve(10000);
 
        // enumerate all boxes: complexity ok since X*Y*Z <= 5000
        for(int x1=1;x1<=X;x1++){
            for(int x2=x1;x2<=X;x2++){
                for(int y1=1;y1<=Y;y1++){
                    for(int y2=y1;y2<=Y;y2++){
                        for(int z1=1;z1<=Z;z1++){
                            for(int z2=z1;z2<=Z;z2++){
                                int vol = (x2-x1+1)*(y2-y1+1)*(z2-z1+1);
                                int s = sum_box(x1,x2,y1,y2,z1,z2);
                                if(s==vol && vol>0){
                                    Box B;
                                    B.cost = min({x2-x1+1, y2-y1+1, z2-z1+1});
                                    B.elems.reserve(vol);
                                    for(int x=x1-1;x<=x2-1;x++){
                                        for(int y=y1-1;y<=y2-1;y++){
                                            for(int z=z1-1;z<=z2-1;z++){
                                                int lin = (x*Y + y)*Z + z;
                                                int idx = lin2idx[lin];
                                                if(idx!=-1) B.elems.pb(idx);
                                            }
                                        }
                                    }
                                    if(!B.elems.empty()) boxes.pb(move(B));
                                    // small safeguard: avoid explosion
                                    if((int)boxes.size() > 200000) break;
                                }
                            }
                            if((int)boxes.size() > 200000) break;
                        }
                        if((int)boxes.size() > 200000) break;
                    }
                    if((int)boxes.size() > 200000) break;
                }
                if((int)boxes.size() > 200000) break;
            }
            if((int)boxes.size() > 200000) break;
        }
 
        // If boxes exploded, fallback: use singletons (each 1×1×1)
        if(boxes.empty()){
            // fall back: each single 1-cell as a box (cost=1)
            for(int i=0;i<U;i++){
                Box B; B.cost = 1; B.elems = {i};
                boxes.pb(move(B));
            }
        } else if((int)boxes.size() > 200000){
            boxes.clear();
            for(int i=0;i<U;i++){
                Box B; B.cost = 1; B.elems = {i};
                boxes.pb(move(B));
            }
        }
 
        int M = boxes.size();
        // covered flag
        vector<char> covered(U, 0);
        int remain = U;
        int totalCost = 0;
 
        // Precompute for speed: each box's elems vector and cost already
        // Greedy loop: pick box with max (newly_covered / cost)
        while(remain > 0){
            double bestVal = -1.0;
            int bestIdx = -1;
            int bestNew = 0;
            for(int i=0;i<M;i++){
                int newly = 0;
                for(int e : boxes[i].elems) if(!covered[e]) ++newly;
                if(newly==0) continue;
                double val = double(newly) / double(boxes[i].cost);
                if(val > bestVal + 1e-12){
                    bestVal = val;
                    bestIdx = i;
                    bestNew = newly;
                }
            }
            if(bestIdx==-1){
                // something wrong -> cover remaining by singletons
                totalCost += remain;
                break;
            }
            totalCost += boxes[bestIdx].cost;
            for(int e : boxes[bestIdx].elems){
                if(!covered[e]) { covered[e]=1; --remain; }
            }
        }
 
        cout<<totalCost<<nl;
    }
    return 0;
}