题意分析: 水平N牌 ,垂直M牌 ,水平相互独立(即不想交) ,垂直也是如此。
可以看出这是一个二分图。
但是水平的牌和垂直的会相交,求最少踢出去几张牌,使得剩下的牌都不相交 。
那么把水平和垂直相交的牌连边,求出最大匹配数,把这些匹配的边切断,剩下的牌就相互不交了。也就是最大独立点。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#define maxn 1010
using namespace std;
int N,M;
struct node
{
int x,y;
} p1[1010],p2[1010];
int lef[maxn];
bool T[maxn];
int cnt;
vector<int> g[1010];
bool match(int u)
{
int i,j;
for(i=0; i<g[u].size(); i++)
{
int v = g[u][i];
if (!T[v])
{
T[v] = true;
if (lef[v] == -1 || match(lef[v]))
{
lef[v] = u;
return true;
}
}
}
return false;
}
int solve()
{
memset(lef, -1, sizeof(lef));
int ans = 0;
int u;
for(u = 1; u <= N; u++)
{
memset(T, 0, sizeof(T));
if(match(u))
{
ans++;
}
}
return ans;
}
bool judge(int a,int b)
{
if(p1[a].x==p2[b].x&&p1[a].y==p2[b].y)
{
return true;
}
if(p1[a].x==p2[b].x&&p1[a].y==p2[b].y+1)
{
return true;
}
if(p1[a].x+1==p2[b].x&&p1[a].y==p2[b].y)
{
return true;
}
if(p1[a].x+1==p2[b].x&&p1[a].y==p2[b].y+1)
{
return true;
}
return false;
}
void build()
{
int i,j;
for(i=1; i<=N; i++)
{
for(j=1; j<=M; j++)
{
if(judge(i,j))
{
g[i].push_back(j);
}
}
}
}
int main()
{
// freopen("input.txt","r",stdin);
int i,j;
while(scanf("%d %d",&N,&M)==2&&N+M)
{
for(i=1; i<=N; i++)
{
scanf("%d %d",&p1[i].x,&p1[i].y);
g[i].clear();
}
for(i=1; i<=M; i++)
{
scanf("%d %d",&p2[i].x,&p2[i].y);
}
build();
int temp=solve();
printf("%d\n",N+M-temp);
}
return 0;
}