题意:给定1×2的多米诺骨牌,放在平面上,可以水平放也可以竖直放,保证水平和水平的之间不重叠,竖直和竖直的不重叠,但水平和竖直的可能重叠。拿走一些牌使它们,不重叠,求平面上最多可以剩张牌。
解法:在重叠的牌之间连边构成二分图,有边相连说明至多只有一张牌能留在平面上。YY出来的结论是,用总牌数减去最大匹配即为所求。
//time 31MS
//memory 1332K
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 1015
using namespace std;
struct Point{
int x,y;
Point(){}
Point(int a,int b):x(a),y(b){}
bool operator ==(const Point &a)const
{
return x==a.x&&y==a.y;
}
void input(){scanf("%d%d",&x,&y);}
};
int link[MAXN],n,m;
bool vis[MAXN],g[MAXN][MAXN];
bool judge(Point a, Point b)
{
if(a==b||Point(a.x+1,a.y)==b||Point(a.x+1,a.y)==Point(b.x,b.y+1)||a==Point(b.x,b.y+1))
return 1;
return 0;
}
bool dfs(int u)
{
for(int i = 0;i < m; i++)
{
if(!vis[i]&&g[u][i])
{
vis[i] = 1;
if(link[i]==-1||dfs(link[i]))
{
link[i] = u;
return 1;
}
}
}
return 0;
}
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
Point pn[MAXN],pm[MAXN];
while(scanf("%d%d",&n,&m)&&(m+n))
{
memset(g,0,sizeof(g));
for(int i = 0; i < n; i++)
pn[i].input();
for(int i = 0; i < m; i++)
pm[i].input();
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
if(judge(pn[i],pm[j]))
g[i][j] = 1;
memset(link,-1,sizeof(link));
int sum=0;
for(int i = 0; i < n; i++)
{
memset(vis,0,sizeof(vis));
sum+=dfs(i);
}
printf("%d\n",n+m-sum);
}
return 0;
}