题目链接:http://acm.fzu.edu.cn/problem.php?pid=2194
思路:对于所有点将与其距离 <= 5 的点连边,然后跑二分图匹配,最后算出最大独立集,这题数据量比较大,用的是Hopcroft-Carp算法,复杂度O(sqrt(n) * E),另外使用map时要使用内置的pair类型和find函数,否则会T。。。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
#include <set>
#include <map>
#include <climits>
#include <functional>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int MAXN = 50010;
const int INF = INT_MAX - 1;
vector <int> G[MAXN];
int uN;
int Mx[MAXN], My[MAXN];
int dx[MAXN], dy[MAXN];
int dis;
bool used[MAXN];
struct node
{
int x, y;
} a[MAXN];
typedef pair <int, int> P;
bool SearchP()
{
queue <int> Q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for (int i = 0 ; i < uN; i++)
if (Mx[i] == -1)
{ Q.push(i);
dx[i] = 0;
}
while (!Q.empty())
{
int u = Q.front();
Q.pop();
if (dx[u] > dis)break;
int sz = G[u].size();
for (int i = 0; i < sz; i++)
{
int v = G[u][i];
if (dy[v] == -1)
{
dy[v] = dx[u] + 1;
if (My[v] == -1)dis = dy[v];
else
{
dx[My[v]] = dy[v] + 1;
Q.push(My[v]);
}
}
}
}
return dis != INF;
}
bool DFS(int u)
{
int sz = G[u].size();
for (int i = 0; i < sz; i++)
{
int v = G[u][i];
if (!used[v] && dy[v] == dx[u] + 1)
{
used[v] = true;
if (My[v] != -1 && dy[v] == dis)continue;
if (My[v] == -1 || DFS(My[v]))
{
My[v] = u;
Mx[u] = v;
return true;
}
}
}
return false;
}
int MaxMatch()
{
int res = 0;
memset(Mx, -1, sizeof(Mx));
memset(My, -1, sizeof(My));
while (SearchP())
{
memset(used, false, sizeof(used));
for (int i = 0; i < uN; i++)
if (Mx[i] == -1 && DFS(i))
res++;
}
return res;
}
map <P, int> ma;
void init(int n)
{
ma.clear();
for (int i = 0; i <= n; i++)
G[i].clear();
}
int main()
{
int n;
while (~scanf("%d", &n))
{
init(n);
for (int i = 0; i < n; i++)
{
scanf("%d%d", &a[i].x, &a[i].y);
ma[P(a[i].x, a[i].y)] = i + 1;
}
uN = n;
map <P, int> ::iterator it;
for (int i = 0; i < n; i++)
{
for (int j = -5; j <= 5; j++)
{
for (int k = -5; k <= 5; k++)
{
if (j * j + k * k > 25) continue;
if (j == 0 && k == 0) continue;
P nxt;
nxt.first = a[i].x + j, nxt.second = a[i].y + k;
it = ma.find(nxt);
if (it->second)
G[i].push_back(it->second - 1);
}
}
}
int res = MaxMatch() / 2;
if (res == n)
puts("-1");
else
printf("%d\n", n - res);
}
return 0;
}