FZU 星系碰撞(二分图匹配+染色)
Problem E 星系碰撞
Accept: 8 Submit: 18
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),没有重合的点。
每行2个整数 x和y 表示星球的坐标(1<=x,y<=500000),没有重合的点。
Output
输出一行一个整数表示最多有多少个星球属于银河系。如果没办法进行划分那么输出-1。
Sample Input
6
1 3
9 1
11 7
5 7
13 5
4 4
1 3
9 1
11 7
5 7
13 5
4 4
Sample Output
4
链接:http://acm.fzu.edu.cn/contest/problem.php?cid=144&sortid=5
题意:给你一对点,你要把它们分成2个集合,每个集合里面的两个点欧几里得距离要大于5,求其中一个集合的最多元素,不行输出-1
思路:给点染色,染到不符合就退出来(二分图模型),但是要优化一下...
题意:给你一对点,你要把它们分成2个集合,每个集合里面的两个点欧几里得距离要大于5,求其中一个集合的最多元素,不行输出-1
思路:给点染色,染到不符合就退出来(二分图模型),但是要优化一下...
代码:
#include<stdio.h>
#include<algorithm>
using namespace std;
const int N = 5e4+10;
struct node
{
int x,y;
bool operator<(node a)const
{
if(x==a.x) return y<a.y;
return x<a.x;
}
}sa[N];
int col[N],n;
int res[3];
bool dis(int i,int j) ///判两点距离是否小于等于5
{
int k1 = abs(sa[i].x-sa[j].x),k2 = abs(sa[i].y-sa[j].y);
if(k1>5||k2>5) return false;
return k1*k1+k2*k2<=25;
}
bool dfs(int u,int c) ///给点染色
{
res[c] ++;
col[u] = c;
for(int i=u+1;i<=n;i++)
{
if(abs(sa[u].x - sa[i].x)>5) break; ///优化:横坐标相差5就可以退出循环了
if(dis(u,i))
{
if(col[u]==col[i]) return false;
if(!col[i]&&!dfs(i,3-c)) return false;
}
}
return true;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d%d",&sa[i].x,&sa[i].y);
col[i] = 0;
}
sort(sa+1,sa+n+1); ///排序做优化
int ans = 0,ok = 1;
for(int i=1;i<=n&&ok;i++)
{
if(!col[i])
{
res[1] = res[2] = 0;
if(!dfs(i,1))
ok = 0;
ans += max(res[1],res[2]); ///取最大的那个集合
// printf("i=%d , res[1]=%d , res[2]=%d\n",i,res[1],res[2]);
}
}
if(!ok)
puts("-1");
else
printf("%d\n",ans);
}
return 0;
}
#include<algorithm>
using namespace std;
const int N = 5e4+10;
struct node
{
int x,y;
bool operator<(node a)const
{
if(x==a.x) return y<a.y;
return x<a.x;
}
}sa[N];
int col[N],n;
int res[3];
bool dis(int i,int j) ///判两点距离是否小于等于5
{
int k1 = abs(sa[i].x-sa[j].x),k2 = abs(sa[i].y-sa[j].y);
if(k1>5||k2>5) return false;
return k1*k1+k2*k2<=25;
}
bool dfs(int u,int c) ///给点染色
{
res[c] ++;
col[u] = c;
for(int i=u+1;i<=n;i++)
{
if(abs(sa[u].x - sa[i].x)>5) break; ///优化:横坐标相差5就可以退出循环了
if(dis(u,i))
{
if(col[u]==col[i]) return false;
if(!col[i]&&!dfs(i,3-c)) return false;
}
}
return true;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d%d",&sa[i].x,&sa[i].y);
col[i] = 0;
}
sort(sa+1,sa+n+1); ///排序做优化
int ans = 0,ok = 1;
for(int i=1;i<=n&&ok;i++)
{
if(!col[i])
{
res[1] = res[2] = 0;
if(!dfs(i,1))
ok = 0;
ans += max(res[1],res[2]); ///取最大的那个集合
// printf("i=%d , res[1]=%d , res[2]=%d\n",i,res[1],res[2]);
}
}
if(!ok)
puts("-1");
else
printf("%d\n",ans);
}
return 0;
}