// Arup Guha
// 5/19/2018
// Solution to 2018 Code Jam Round 2 Problem C: Costume Change

// Can't believe I didn't get this in contest :(

import java.util.*;

public class Solution {

	public static int n;
	public static int[][] grid;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int nC = stdin.nextInt();

		// Process each case.
		for (int loop=1; loop<=nC; loop++) {

			// Get the grid.
			n = stdin.nextInt();
			grid = new int[n][n];
			for (int i=0; i<n; i++)
				for (int j=0; j<n; j++)
					grid[i][j] = stdin.nextInt();

			// Remap each unique costume to an id number starting at 0.
			int id = 0;
			HashMap<Integer,Integer> cMap = new HashMap<Integer,Integer>();
			for (int i=0; i<n; i++)
				for (int j=0; j<n; j++)
					if (!cMap.containsKey(grid[i][j]))
						cMap.put(grid[i][j],id++);

			// Remap.
			for (int i=0; i<n; i++)
				for (int j=0; j<n; j++)
					grid[i][j] = cMap.get(grid[i][j]);

			// For each id number, store which grid cells have it.
			ArrayList[] lists = new ArrayList[id];
			for (int i=0; i<id; i++) lists[i] = new ArrayList<Integer>();
			for (int i=0; i<n; i++)
				for (int j=0; j<n; j++)
					lists[grid[i][j]].add(n*i+j);

			int unique = 0;

			// Try out each dress.
			for (int i=0; i<id; i++) {

				// Put capacity 1 from s->row, and col->t.
				Dinic g = new Dinic(2*n);
				for (int j=0; j<n; j++)
					g.add(g.s, j, 1, 0);
				for (int j=n; j<2*n; j++)
					g.add(j, g.t, 1, 0);

				// Put an edge for each cell from its row to its column.
				for (Integer x: (ArrayList<Integer>)lists[i]) {
					int myr = x/n;
					int myc = x%n;
					g.add(myr, n+myc, 1, 0);
				}

				// The max flow of this graph is the most number of people with dress id
				// that can keep their dress, so add this to our not changing count.
				unique += g.flow();
			}

			// Ta da!
			System.out.println("Case #"+loop+": "+(n*n-unique));
		}
	}
}

class Edge {
	int v1, v2, cap, flow;
	Edge rev;
	Edge(int V1, int V2, int Cap, int Flow) {
		v1 = V1; v2 = V2; cap = Cap; flow = Flow;
	}
}

class Dinic {

	ArrayDeque<Integer> q;
	ArrayList<Edge>[] adj;
	int n, s, t, oo = (int)1E9;
	boolean[] blocked;
	int[] dist;

	public Dinic (int N) {
		n = N; s = n++; t = n++;
		blocked = new boolean[n];
		dist = new int[n];
		q = new ArrayDeque<Integer>();
		adj = new ArrayList[n];
		for(int i = 0; i < n; ++i)
			adj[i] = new ArrayList<Edge>();
	}

	void add(int v1, int v2, int cap, int flow) {
		Edge e = new Edge(v1, v2, cap, flow);
		Edge rev = new Edge(v2, v1, 0, 0);
		adj[v1].add(rev.rev = e);
		adj[v2].add(e.rev = rev);
	}

	boolean bfs() {
		q.clear();
		Arrays.fill(dist, -1);
		dist[t] = 0;
		q.add(t);

		while(!q.isEmpty()) {
			int node = q.poll();
			if(node == s)
				return true;
			for(Edge e : adj[node]) {
				if(e.rev.cap > e.rev.flow && dist[e.v2] == -1) {
					dist[e.v2] = dist[node] + 1;
					q.add(e.v2);
				}
			}
		}
		return dist[s] != -1;
	}

	int dfs(int pos, int min) {
		if(pos == t)
			return min;
		int flow = 0;
		for(Edge e : adj[pos]) {
			int cur = 0;
			if(!blocked[e.v2] && dist[e.v2] == dist[pos]-1 && e.cap - e.flow > 0) {
				cur = dfs(e.v2, Math.min(min-flow, e.cap - e.flow));
				e.flow += cur;
				e.rev.flow = -e.flow;
				flow += cur;
			}
			if(flow == min)
				return flow;
		}
		blocked[pos] = flow != min;
		return flow;
	}

	int flow() {
		clear();
		int ret = 0;
		while(bfs()) {
			Arrays.fill(blocked, false);
			ret += dfs(s, oo);
		}
		return ret;
	}

	void clear() {
		for(ArrayList<Edge> edges : adj)
			for(Edge e : edges)
				e.flow = 0;
	}
}