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),没有重合的点。

Output


输出一行一个整数表示最多有多少个星球属于银河系。如果没办法进行划分那么输出-1。

Sample Input

6
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
思路:给点染色,染到不符合就退出来(二分图模型),但是要优化一下...
 
代码:
#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>5return 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)>5break///优化:横坐标相差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;
}
View Code

posted @ 2015-05-04 18:02  Doli  阅读(223)  评论(0编辑  收藏  举报