hdu 1507【Uncle Tom's Inherited Land*】

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

vector<int> land[100];
int link[100];
bool vis[100];
int g[110][110];
bool vis2[100];
int pond[100];
int n,m,k;

bool can(int x)
{
	int len = land[x].size();
	for(int i = 0;i < len;i ++)
	{
		int t = land[x].at(i);
		if(!vis[t])
		{
			vis[t] = true;
			if(link[t] == -1 || can(link[t]))
			{
				link[t] = x;
				return true;
			}
		}
	}

	return false;
}

int maxmatch(int count)
{
	int num = 0;
	memset(link,-1,sizeof(link));
	for(int i = 1;i <= count;i ++)
	{
		memset(vis,false,sizeof(vis));
		if(can(i))
			num ++;
	}
	/*for(int i = 1;i <= count;i ++)
	{
		if(link[i] != -1)
			printf("link[%d]:%d\n",i,link[i]);
	}*/

	return num;
}

void print()
{
	memset(vis2,false,sizeof(vis2));
	for(int i = 1;i <= n;i ++)
	{
		for(int j = 1;j <= m;j ++)
		{
			if(g[i][j]&&!vis2[g[i][j]]&&link[g[i][j]] != -1&&!vis2[link[g[i][j]]])
			{
				int ax = (g[i][j] + pond[g[i][j]] - 1)/m + 1;//pond的作用就在这里,将编号还原为矩形的一格一格编号
				int ay = (g[i][j] + pond[g[i][j]]-1)%m+1;
				int bx = (link[g[i][j]] + pond[link[g[i][j]]] - 1)/m +1;
				int by = (link[g[i][j]] + pond[link[g[i][j]]]-1) % m+1;
				vis2[g[i][j]] = true;//将访问过的点标记
				vis2[link[g[i][j]]] = true;
				printf("(%d,%d)--(%d,%d)\n",ax,ay,bx,by);
			}
		}
	}

	printf("\n");
}

int main()
{
	while(scanf("%d%d",&n,&m),n || m)
	{
		memset(g,-1,sizeof(g));
		memset(pond,0,sizeof(pond));
		scanf("%d",&k);
		for(int i = 0;i < 55;i ++)
		{
			land[i].clear();
		}
		for(int i = 0;i < k;i ++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			g[a][b] = 0;
		}

		int t = 0;
		int count = 1;
		for(int i = 1;i <= n;i ++)
		{
			for(int j = 1;j <= m;j ++)
			{
				if(g[i][j] == 0)
				{
					t ++;
				}
				else
				{
					pond[count] = t;//记录land前面pond的个数
					//printf("pond[%d]:%d\n",count,t);
					g[i][j] = count ++;//给每个land编号
				}
			}
		}

		for(int i = 1;i <= n;i ++)
		{
			for(int j = 1;j <= m;j ++)
			{
				//printf("%d ",g[i][j]);
				if(g[i][j] != 0)
				{
					if(i-1>0&&g[i-1][j] != 0)
					{
						land[g[i][j]].push_back(g[i-1][j]);
					}
					if(i +1 <=m && g[i+1][j] != 0)
					{
						land[g[i][j]].push_back(g[i + 1][j]);
					}
					if(j - 1> 0&& g[i][j -1] != 0)
					{
						land[g[i][j]].push_back(g[i][j-1]);
					}
					if(j + 1 <= n&&g[i][j + 1] != 0)
					{
						land[g[i][j]].push_back(g[i][j+1]);
					}
				}
			}
			//printf("\n");
		}

		printf("%d\n",maxmatch(count - 1) / 2);
		print();
	}

	return 0;
}

一A,太兴奋了,(*^__^*) 嘻嘻……而且效率还蛮不错滴 15MS 292K。

二分匹配来着,只不过题目要求我们输出匹配的方案

本来之前打算来个暴力的,但是N*M可达1万,然后嘞,题目又说N*M-K<=50,就改变策略了,给不是池塘的land编号,并记录每个land前面的池塘数目(记录池塘的数目是方便输出的,题目要求我们输出匹配的行与列,反正land也就50个),这样编号的land最多也就50个了。

可是就是还有人0ms过的,(~ o ~)~zZ崇拜

原文地址:https://www.cnblogs.com/Shirlies/p/2497987.html