有n张水平放置的牌 占据(x, y) and (x + 1, y).m张竖直放置的牌占据 (x, y) and (x, y + 1).,同向放置的牌的位置不会重复,但是横着的和竖着的牌的位置会重复,问最多有多少张不会重复的牌。
典型的二分图匹配,把会重复的牌的位置建立一条边,然后套模板,最后得到点的最大独立个数=顶点数-匹配个数。
#include <iostream>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=1111;
struct Point
{
int x,y;
}a1[maxn],a2[maxn];
int map[maxn][maxn];
int link[maxn];
int visit[maxn];
int n,m;
bool dfs(int k)
{
for(int i=0;i<m;i++)
{
if(!visit[i]&&map[k][i])
{
visit[i]=1;
int j=link[i];
if(j==-1||dfs(j))
{
link[i]=k;
return true;
}
}
}
return false;
}
int hungry()
{
int ans=0;
for(int i=0;i<n;i++)
{
memset(visit,0,sizeof(visit));
if(dfs(i))
{
ans++;
}
}
return ans;
}
bool dis(Point a,Point b)
{
if(a.x == b.x && a.y == b.y)
return true;
if(a.x == b.x && a.y == b.y + 1)
return true;
if(a.x + 1 == b.x && a.y == b.y)
return true;
if(a.x + 1 == b.x && a.y == b.y + 1)
return true;
return false;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
{
break;
}
memset(link,-1,sizeof(link));
memset(map,0,sizeof(map));
for(int i=0;i<n;i++)
{
scanf("%d%d",&a1[i].x,&a1[i].y);
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&a2[i].x,&a2[i].y);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(dis(a1[i],a2[j]))
{
map[i][j]=1;
}
}
}
int ans=hungry();
printf("%d\n",n+m-ans);
}
return 0;
}