Problem 2194 星系碰撞
Accept: 29 Submit: 102
Time Limit: 30000 mSec Memory Limit : 327680 KB
Problem Description
据预测,大约在100亿年后,狮子座星系将与银河系发生碰撞,两个星系的碰撞将会合并两个星系,但是没有2个星球会相撞。现在某科学家得到两个星系合并后的结果,一些二维平面上的点,但是不知道那些星球属于银河系,已知如果两个星球属于同一个星系,那么他们之间的距离大于5光年,这边的距离指的是欧几里得距离,即(x1,y1)与(x2,y2)的距离为sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))。现在想请你帮忙把合并后的结果分成2个集合,一个属于银河系,一个属于狮子座星系,由于集合划分的方案可能有多种,现在想知道最多有多少个星球可能属于银河系。(可以所有星球都属于银河系)
例如:如下图有6个点,你可以有以下4中划分{{1, 2, 4, 5}, {3, 6}}; {{1, 2, 3, 4}, {5, 6}}; {{1, 4,5}, {2, 3, 6}}; {{1, 3, 4}, {2, 5, 6}} ,那么可以采用第一种划分{1,2,4,5} 都属于银河系,答案为4.
Input
包含多组数据每组数据输入第一行 一个整数N 表示星球个数(1<=N<=50000),接下去N 行 每行2个整数 x和y 表示星球的坐标(1<=x,y<=500000),没有重合的点。
Output
输出一行一个整数表示最多有多少个星球属于银河系。如果没办法进行划分那么输出-1。
Sample Input
61 39 111 75 713 54 4
Sample Output
4
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <cstring>
#define INF 100000000
using namespace std;
struct node{
int x,y;
bool operator < (const node & a)const {
return x < a.x;
}
};
node a[50005];
vector<int> vec[50005];
int cx[50005];
int cy[50005];
int visit[50005];
int n;
int path(int u){
int cc = vec[u].size();
for(int i = 0;i < cc;i++){
int v = vec[u][i];
if(!visit[v]){
visit[v] = 1;
if(cy[v] == -1 || path(cy[v])){
cy[v] = u;
cx[u] = v;
return 1;
}
}
}
return 0;
}
int color[50005];
int flag;
int maxmatch(int u){
queue<int> que;
color[u] = 1;
que.push(u);
vector<int> va;
va.push_back(u);
while(!que.empty()){
int t = que.front();
que.pop();
int cc = vec[t].size();
for(int i = 0;i < cc;i++){
int v = vec[t][i];
if(color[v] == -1){
color[v] = (color[t] + 1)%2;
if(color[v]){
va.push_back(v);
}
que.push(v);
}
else{
if(color[v] == color[t]){
flag = 1;
}
}
}
}
int cc = va.size();
int res = 0;
for(int i = 0;i < cc;i++){
int v = va[i];
if(cx[v] == -1){
memset(visit,0,sizeof(visit));
res += path(v);
}
}
return res;
}
int d(int i,int j){
return (a[i].x - a[j].x)*(a[i].x - a[j].x) + (a[i].y - a[j].y)*(a[i].y - a[j].y);
}
int main(){
while(cin >> n){
for(int i = 0;i < n;i++){
scanf("%d%d",&a[i].x,&a[i].y);
vec[i].clear();
}
sort(a,a+n);
for(int i = 0;i < n;i++){
for(int j = i+1;a[j].x - a[i].x <= 5&& j < n;j++){
if(d(i,j) <= 25){
vec[i].push_back(j);
vec[j].push_back(i);
}
}
}
int tm = 0;
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
memset(color,-1,sizeof(color));
flag = 0;
for(int i = 0;i < n && !flag;i++){
if(vec[i].size()){
if(color[i] == -1)
tm += maxmatch(i);
}
}
if(flag){
cout << -1 << endl;
}
else{
cout << (n-tm) << endl;
}
}
return 0;
}