poj 2226 Muddy Fields 最小点覆盖

       转换成求最小点覆盖数

       构图方式如下:横行的连续*方块作为X集合里的顶点,纵行的连续*方块作为Y集合的顶点,若两个方块相交,则用边把这两个顶点相连。然后求最小点覆盖数(求最大匹配),即为答案。

       要注意构图后的顶点数。

 

#include <iostream>

#include <cstring>

using namespace std;



const int N = 55;

const int MAX = N*N;



struct Xblock

{

	int x;

	int sty, edy;

};



struct Yblock

{

	int y;

	int stx, edx;

};



Xblock xblock[MAX];

Yblock yblock[MAX];

bool maze[MAX][MAX];

char map[N][N];

bool isvisit[MAX];

int match[MAX];



int cnt_x, cnt_y;

int row, col;



void build_graph()

{

	cnt_x = 0;

	cnt_y = 0;



	for (int i = 0; i < row; i++)

		for (int j = 0; j < col; j++)

		{

			if (map[i][j] == '*')

			{

				xblock[cnt_x].x = i;

				xblock[cnt_x].sty = j;

				while (j < col && map[i][j] == '*')

				{

					xblock[cnt_x].edy = j;

					j++;

				}

				cnt_x++;

			}

		}



	for (int j = 0; j < col; j++)

		for (int i = 0; i < row; i++)

		{

			if (map[i][j] == '*')

			{

				yblock[cnt_y].y = j;

				yblock[cnt_y].stx = i;



				while (i < row && map[i][j] == '*')

				{

					yblock[cnt_y].edx = i;

					i++;

				}

				cnt_y++;

			}

		}



	memset(maze, false, sizeof(maze));

	for (int i = 0; i < cnt_x; i++)

		for (int j = 0; j < cnt_y; j++)

			if (xblock[i].x >= yblock[j].stx && xblock[i].x <= yblock[j].edx

				&& yblock[j].y >= xblock[i].sty && yblock[j].y <= xblock[i].edy)

				maze[i][j] = true;

}



bool find(int u)

{

	for (int i = 0; i < cnt_y; i++)

	{

		if (maze[u][i] && !isvisit[i])

		{

			isvisit[i] = true;

			if (match[i] == -1 || find(match[i]))

			{

				match[i] = u;

				return true;

			}

		}

	}

	return false;

}



int main()

{

	cin >> row >> col;



	for (int i = 0; i < row; i++)

		for (int j = 0; j < col; j++)

			cin >> map[i][j];



	build_graph();



	memset(match, -1, sizeof(match));

	int ans = 0;

	for (int i = 0; i < cnt_x; i++)

	{

		memset(isvisit, false, sizeof(isvisit));

		if (find(i))

			ans++;

	}



	cout << ans << endl;

	return 0;

}

你可能感兴趣的:(Field)