2部グラフのマッチング

2008年のGoogle Code Jamをちょっとだけやった.
2部グラフのマッチングの応用があった.
模範回答(?)のコードが想像以上に短かった.

こんな感じ.

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

#define FILL(xs, x) memset(xs, x, sizeof((xs)))

const int M = 100, N = 100;
int m, n, ind, matchX[M][N], matchY[M][N], visited[M][N], count;
bool room[M][N];

bool dfs(int x, int y)
{
  if (x < 0) return true;
  if (visited[x][y] == count) return false;
  visited[x][y] = count;
  for (int i = x-1; i <= x+1; i++)
	for (int j = y-1; j <= y+1; j+=2)
	  if (0 <= i && i < m && 0 <= j && j < n && room[i][j])
		if ( dfs(matchX[i][j], matchY[i][j]) )
		  {
			matchX[i][j] = x; matchY[i][j] = y;
			matchX[x][y] = i; matchY[x][y] = j;
			return true;
		  }
  return false;
}

int solve()
{
  int ret = 0; count = 0;
  FILL(matchX,-1); FILL(matchY,-1); FILL(visited,0);

  for (int i = 0; i < m; i++)
	for (int j = 0; j < n; j++)
	  if (room[i][j])
        {
          ret++;
          if (j%2==1)
            {
              count++;
              if (dfs(i,j)) ret--;
            }
        }
  return ret;
}

int main()
{
  int testCase;
  cin >> testCase;
  for (int iCase = 1; iCase <= testCase; iCase++)
	{
	  cin >> m >> n;
	  for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
		  {
			char c;
			cin >> c;
			room[i][j] = c == '.';
		  }
	  cout << "Case #" << iCase << ": " << solve() << endl;
	}
  return 0;
}

無駄が無いコードになっている.再帰をつかって簡潔になっている.
2部グラフのマッチングはこういうふうに書ける,というのは常識なんでしょうか?