Problem 2194 星系碰撞
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
一开始没看见是多组数据WA了好几发,原来用map做发现会T于是自己手写了个hash,二分图判断加染色,然后把几个连通分量中较大的一侧累加起来就是答案。
一开始没看见是多组数据WA了好几发,原来用map做发现会T于是自己手写了个hash,二分图判断加染色,然后把几个连通分量中较大的一侧累加起来就是答案。
#include <cmath>
#include <cstring>
#include <cstdio>
#include <utility>
#include <iostream>
#include <algorithm>
using namespace std;
struct point
{
long long x,y;
} a[50002];
struct v
{
int num,next;
} b[5000000];
pair <int ,int> f[521373+50002];
bool flag;
int jud[521373+50002],val[521373+50002];
void Insert(pair <int ,int > x,int v)
{
int k=(x.first%23333)*10+x.second%521373;
while(jud[k] && f[k] != x) k++;
jud[k]=1;
f[k]=x;
val[k]=v;
}
int find(pair <int ,int > x)
{
int k=(x.first%23333)*10+x.second%521373;
while(jud[k] && f[k] != x) k++;
if(jud[k] == 0) return 0;
return val[k];
}
int n,A[50002],col[50002],Tot,ans[3],Ans;
long long x,y;
void insert(int x,int y)
{
Tot++;
b[Tot].num=y;
b[Tot].next=A[x];
A[x]=Tot;
}
void dfs(int x)
{
int k=A[x];
while(k)
{
int j=b[k].num;
if(col[j] == 0)
{
col[j]=3-col[x];
ans[col[j]]++;
dfs(j);
if(flag) return;
}
else
if(col[j] == col[x])
{
flag=true;
return ;
}
k=b[k].next;
}
}
int main()
{
cin.sync_with_stdio(false);
while(cin>>n)
{
Tot=0,Ans=0;
memset(A,0,sizeof(A));
memset(col,0,sizeof(col));
memset(jud,0,sizeof(jud));
for(int i=1;i <= n;i++)
{
cin>>a[i].x>>a[i].y;
Insert(make_pair(a[i].x,a[i].y),i);
}
for(int i=1;i <= n;i++)
{
for(x=a[i].x;x <= a[i].x+5;x++)
for(y=a[i].y-5;y <= a[i].y+5;y++)
if((x != a[i].x || y != a[i].y) && ((x-a[i].x)*(x-a[i].x)+(y-a[i].y)*(y-a[i].y) <= 25ll))
{
int now=find(make_pair(x,y));
if(now == 0) continue;
insert(now,i);
insert(i,now);
}
}
flag=false;
for(int i=1;i <= n;i++)
if(col[i] == 0)
{
col[i]=1;
ans[1]=ans[2]=0;
ans[1]++;
dfs(i);
if(flag) break;
Ans+=max(ans[1],ans[2]);
}
if(flag)
{
cout<<"-1"<<endl;
continue;
}
cout<<Ans<<endl;
}
}