zoukankan      html  css  js  c++  java
  • Fzu oj2194星系碰撞(排序+并查集+路径压缩)

    Problem 2194 星系碰撞

    Accept: 14    Submit: 48
    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
    分析:把所有的行星按照x坐标从小到大排序,然后枚举两点(加剪枝)距离,若距离小于等于5,若这两个点不在一个集合当中,则加入一个集合,并且这两个相连的点染为不同的颜色,若这两个点在一个集合当中,则判定矛盾,因为再改集合中至少有三个点,他们两两之间的距离都小于等于5,就是说无论怎样分配他们都无法满足题目要求,如果不存在矛盾的情况,则计算出每个集合当中被染成两种颜色的个数max1和max2,最后把所有集合当中的较大者加起来即:sum+=max(max1[k]+max2[k])(k属于不同的集合)
    程序;
    #include"stdio.h"
    #include"string.h"
    #include"math.h"
    #include"iostream"
    #include"queue"
    #include"algorithm"
    #include"stack"
    #include"map"
    #include"string"
    #define M 50009
    #define inf 0x3f3f3f3f
    #define eps 1e-9
    #define LL __int64
    using namespace std;
    struct node
    {
        int x,y;
    }p[M];
    int cmp(node a,node b)
    {
        return a.x<b.x;
    }
    LL dist(node a,node b)
    {
        return (LL)(a.x-b.x)*(a.x-b.x)+(LL)(a.y-b.y)*(a.y-b.y);
    }
    int f[M],max1[M],max2[M],sum[M];
    int finde(int x)
    {
        if(x!=f[x])
        {
            int t=f[x];
            f[x]=finde(f[x]);
            sum[x]=(sum[x]+sum[t])%2;
        }
        return f[x];
    }
    int ok(int n)
    {
        for(int i=0;i<n;i++)
        {
            f[i]=i;
            sum[i]=0;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                if(p[j].x-p[i].x>5)break;
                if(dist(p[i],p[j])<=25LL)
                {
                    int x=finde(i);
                    int y=finde(j);
                    if(x!=y)
                    {
                        f[y]=x;
                        sum[y]=(sum[x]+sum[i]+1-sum[j])%2;
                    }
                    else
                    {
                        if(sum[x]==sum[y])
                        return -1;
                    }
    
                }
            }
        }
        memset(max1,0,sizeof(max1));
        memset(max2,0,sizeof(max2));
        for(int i=0;i<n;i++)
        {
            int y=finde(i);
            f[i]=y;
            if(sum[i]==0)
                max1[y]++;
            else
                max2[y]++;
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            if(f[i]==i)
            {
                ans+=max(max1[i],max2[i]);
            }
        }
        return ans;
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            for(int i=0;i<n;i++)
            {
                scanf("%d%d",&p[i].x,&p[i].y);
            }
            sort(p,p+n,cmp);
            printf("%d
    ",ok(n));
        }
        return 0;
    }
    

      

  • 相关阅读:
    点击按钮生成遮罩层后这个按钮被遮住还可以点击解决办法
    关于jq的load不用回调获取其中dom元素方法
    移动端默认返回按键,使用h5+修改默认事件
    移动端解决input focus后键盘弹出,高度被挤压的问题
    模拟移动端上拉超过页面实际高度
    软工作业
    一周进度汇报
    alhpa阶段回顾
    一周进度汇报
    一周进度汇报
  • 原文地址:https://www.cnblogs.com/mypsq/p/4477233.html
Copyright © 2011-2022 走看看