POJ 1127

并查集+上判断两条线段是否相交就可以了,仔细看数据集非常小,所以基本上可以不用考虑时间复杂度;

本题的难点主要是判断两条线段是否相交;特殊情况比较多,具体的见代码:

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<algorithm>
using namespace std;
struct edge//边;
{
    int x1,y1,x2,y2;
}e[15];
struct point//点;
{
    int x,y;
};
int father[15];
int n;
int find(int x)//以下是最基础的并查集在这里就不多说了;
{
    if(x==father[x]) return x;
    else
        return father[x]=find(father[x]);
}
void unite(int x,int y)
{
    int xx=find(x);
    int yy=find(y);
    if(yy==xx) return;
    else
        father[yy]=xx;
    return;
}
/*bool same(int x,int y)
{
    return find_father(x)==find_father(y);
}*/
int judge(edge a,edge b)//这里是利用计算集合里面判断2个点是否在一条直线两边的方法,使用两次证明p1、p2在直线q1q2的两侧以及q1、q2在直线p1p2的两侧
{
    point p1,p2,q1,q2,p,q;
    p1.x=a.x1,p1.y=a.y1;
    p2.x=a.x2,p2.y=a.y2;
    q1.x=b.x1,q1.y=b.y1;
    q2.x=b.x2,q2.y=b.y2;
    p.x=p1.x-p2.x,p.y=p1.y-p2.y;
    q.x=q1.x-q2.x,q.y=q1.y-q2.y;
    int judgea,judgeb;
    judgea=((q.x*(p1.y-q1.y))-(q.y*(p1.x-q1.x)))*((q.x*(p2.y-q1.y)-(q.y*(p2.x-q1.x))));
    judgeb=((p.x*(q1.y-p1.y))-(p.y*(q1.x-p1.x)))*((p.x*(q2.y-p1.y)-(p.y*(q2.x-p1.x))));

    if(judgea<=0&&judgeb<=0) return 1;//取等号就是考虑一条线段的端点可能在另一条线段上;
    else
        return 0;
}//但是只有这个是有特殊情况的考虑(1,1)-(2,2);(3,3)-(4,4)的情况,他们在同一条直线上但是不相交;所以有了judge2函数
int judge2(edge a,edge b)//这个函数主要是判断以这两条直线段为对角线的矩形是否有交集;显然如果没有交集显然来那个直线段不相交;
{
    int minax=min(a.x1,a.x2);
    int maxax=max(a.x1,a.x2);
    int minay=min(a.y1,a.y2);
    int maxay=max(a.y1,b.y2);
    int minbx=min(b.x1,b.x2);
    int maxbx=max(b.x1,b.x2);
    int minby=min(b.y1,b.y2);
    int maxby=max(b.y1,b.y2);
    if(maxax<minbx||maxay<minby||maxbx<minax||maxby<minay) return 0;
    else
        return 1;
}
int main()
{
    int inputa,inputb;
    while(scanf("%d",&n)!=EOF&&n)
    {
        for(int i=0;i<=n;i++) father[i]=i;//并查集的初始化;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&e[i].x1,&e[i].y1,&e[i].x2,&e[i].y2);
        }
        for(int i=1;i<=n;i++)//枚举两两直线段之间是否相交
        {
            for(int j=i+1;j<=n;j++)
            {
                if(judge(e[i],e[j])==1&&judge2(e[i],e[j])==1)//判断条件;
                {
                    unite(i,j);//如果相交那么他们的根就相同,用并查集将他们合并;
                }
            }
        }
        while(scanf("%d%d",&inputa,&inputb)!=EOF)
        {
            if(inputa==0&&inputb==0) break;
            if(find(inputa)==find(inputb)) printf("CONNECTED\n");
            else
            printf("NOT CONNECTED\n");
        }
    }
    return 0;
}
顺便纪念一下。。计算几何第一题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值