• [poj 1127]Jack Straws[线段相交][并查集]


    题意:

    给出一系列线段,判断某两个线段是否连通.

    思路:

    根据线段相交情况建立并查集, 在同一并查集中则连通.

    (第一反应是强连通分量...实际上只要判断共存即可, 具体的方向啊是没有关系的..)


    并查集合并的时候是根节点合并.

    快速排斥试验不是必需的, 大规模数据可能是个优化吧.

    跨立试验注意共线的情况.

    共线判断注意与y 轴平行的情况.

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    using namespace std;
    const double EPS = 1e-6;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 15;
    typedef struct node
    {
        double x,y;
    }point;
    point a[MAXN],b[MAXN];
    bool adj[MAXN][MAXN];
    int n;
    
    int max(int a, int b)
    {
        int diff = b - a;
        return b - (diff & (diff>>31));
    }
    int min(int a, int b)
    {
        int diff = b - a;
        return a + (diff & (diff>>31));
    }
    int fa[MAXN];
    
    int FindSet(int x)
    {
        if(x==fa[x])    return fa[x];
        return fa[x] = FindSet(fa[x]);
    }
    
    int dcmp(double p)
    {
        if(fabs(p)<EPS)  return 0;
        return p>0?1:-1;
    }
    
    double det(double x1, double y1, double x2, double y2)
    {
        return x1*y2 - x2*y1;
    }
    
    double cross(point A, point B, point P)
    {
        return det(B.x - A.x, B.y - A.y, P.x - A.x, P.y - A.y);
    }
    
    bool ck(point A, point B, point C, point D)
    {
        int min1x = min(A.x,B.x), min2x = min(C.x,D.x);
        int max1x = max(A.x,B.x), max2x = max(C.x,D.x);
        int min1y = min(A.y,B.y), min2y = min(C.y,D.y);
        int max1y = max(A.y,B.y), max2y = max(C.y,D.y);
        /*if(max(max1x,max2x)-min(min1x,min2x)>(max1x-min1x)+(max2x+min2x) ||
           max(max1y,max2y)-min(min1y,min2y)>(max1y-min1y)+(max2y+min2y))   return false;*/
        int a = dcmp(cross(A, B, C));
        int b = dcmp(cross(A, B, D));
        if(!a && !b)
            return (   max(max1x,max2x)-min(min1x,min2x)<=(max1x-min1x)+(max2x-min2x)
                    && max(max1y,max2y)-min(min1y,min2y)<=(max1y-min1y)+(max2y-min2y)  );
        int c = dcmp(cross(C, D, A));
        int d = dcmp(cross(C, D, B));
        return (( a* b <= 0) && ( c* d <= 0));//规范或不规范相交
    }
    
    void BuildSet()
    {
        for(int i=1;i<=n;i++)
        {
            fa[i] = i;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(ck(a[i],b[i],a[j],b[j]))
                {
                    int fi = FindSet(i), fj = FindSet(j);//并查集写错了= =
                    fa[fi] = fj;
                }
            }
        }
    }
    
    bool check(int a, int b)
    {
        return (FindSet(a)==FindSet(b));
    }
    
    int main()
    {
        int x, y;
        while(scanf("%d",&n)==1 && n)
        {
            for(int i=1;i<=n;i++)
                scanf("%lf %lf %lf %lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
            BuildSet();
            while(scanf("%d %d",&x,&y)==2 && (x+y))
            {
                if(check(x, y)) printf("CONNECTED
    ");
                else    printf("NOT CONNECTED
    ");
            }
        }
    
    }
    


  • 相关阅读:
    NGUI Sprite 和 Label 改变Layer 或父物体后 未更新深度问题
    unity销毁层级物体及 NGUI 深度理解总结
    unity 2d 和 NGUI layer
    关于NGUI与原生2D混用相互遮盖的问题心得
    CentOS7为firewalld添加开放端口及相关操作
    Python 操作redis有序集合(sorted set)
    win10下安装redis 服务
    python2/3中 将base64数据写成图片,并将图片数据转为16进制数据的方法、bytes/string的区别
    解决最小化安装Centos7后无法上网的问题,以及安装成功后的基本配置
    在mysql中使用group by和order by取每个分组中日期最大一行数据,亲测有效
  • 原文地址:https://www.cnblogs.com/riskyer/p/3283371.html
Copyright © 2020-2023  润新知