/*
Subject: 匈牙利算法 建图难 经典好题
Author : a_clay
Created Date : 2011-11-25
Sample : zoj 1654
*/
/* 有的课件上就有讲解 */
/*
* Subject : Hungary zoj 1654 经典之作 - 绝佳好题
* Author :a_clay
* Created : 2012-06-07
*/
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
//#include <conio.h>
using namespace std;
const int N = 55;
const int M = 2505;
char str[N][N];
int p[N][N];
int rp[N][N];
int map[M][M];
bool vis[M];
int pre[M];
int n, m;
int x_id, y_id;
bool dfs(int u) {
int i;
for(i = 1; i <= y_id; i++) {
if(map[u][i] && !vis[i]) {
vis[i] = 1;
if(!pre[i] || dfs(pre[i])) {
pre[i] = u;
return true;
}
}
}
return false;
}
int MaxMatch() {
int i, num = 0;
for(i = 1; i <= x_id; i++) {
memset(vis, 0, sizeof(vis));
if(dfs(i)) num++;
}
return num;
}
int main() {
int T, i, j, k, ca = 0;
scanf("%d", &T);
while(T--) {
memset(p, 0, sizeof(p));
memset(rp, 0, sizeof(rp));
scanf("%d%d", &m, &n); // m 行 , n 列
x_id = 0, y_id = 0;
for(i = 0; i < m; i++) {
scanf("%s", str[i]);
}
for(i = 0; i < m; i++) { // 管理行的。。。
int k = 0;
while(k < n) {
if(str[i][k] == 'o') {
++x_id;
while(k < n && str[i][k] != '#') {
p[i][k] = x_id;
k++;
}
}
else k++;
}
}
for(i = 0; i < n; i++) {
int k = 0;
while(k < m) {
if(str[k][i] == 'o') {
++y_id;
while(k < m && str[k][i] != '#') {
rp[k][i] = y_id;
k++;
}
}
else k++;
}
}
memset(map, 0, sizeof(map));
for(i = 0; i < m; i++) {
for(j = 0; j < n; j++) {
if(str[i][j] == 'o') {
map[p[i][j]][rp[i][j]] = 1;
}
}
}
memset(pre, 0, sizeof(pre));
printf("Case :%d\n%d\n", ++ca, MaxMatch());
}
//getch();
//system("pause");
return 0;
}