Hdu 1558 Segment set(并查集+几何)

58 篇文章 0 订阅
11 篇文章 0 订阅
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1558

思路:判断线段相交(注意端点相交),若相交并入同一集合。

#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debu
using namespace std;
const double eps=1e-10;
const int maxn=1e3+50;
const int INF=0x3f3f3f3f;
struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {}
};
struct Line
{
    Point x,y;
    Line(Point x=NULL,Point y=NULL):x(x),y(y) {}
};
typedef Point Vector;
Vector operator - (const Point &A,const Point &B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
int n,tot;
Line L[maxn];
int fa[maxn],w[maxn];
int dcmp(double x)
{
    if(fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
bool operator == (const Point &a, const Point &b)
{
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
double Dot(const Vector &A,const Vector &B)
{
    return A.x*B.x+A.y*B.y;
}
double Cross(const Vector &A,const Vector &B)
{
    return A.x*B.y-A.y*B.x;
}
bool SegmentProperIntersection(const Point &a1, const Point &a2, const Point &b1, const Point &b2)
{
    double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1), c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
    return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}
bool OnSegment(Point p,Point a1,Point a2)
{
    return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
int Find(int x)
{
    return fa[x]==x?x:fa[x]=Find(fa[x]);
}
void Union(int x,int y)
{
    fa[x]=y;
    w[y]+=w[x];
}
void init()
{
    tot=0;
    for(int i=1; i<=n; i++)
    {
        w[i]=1;
        fa[i]=i;
    }
}
int check(Point p,Point x,Point y)
{
    return p==x||p==y;
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    int t,cas=0;
    scanf("%d",&t);
    while(t--)
    {
        cas++;
        if(cas!=1) printf("\n");
        scanf("%d",&n);
        init();
        for(int i=0; i<n; i++)
        {
            char ch;
            getchar();
            scanf("%c",&ch);
            if(ch=='P')
            {
                tot++;
                double x1,y1,x2,y2;
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                Point tmp1=Point(x1,y1),tmp2=Point(x2,y2);
                L[tot]=Line(tmp1,tmp2);
                for(int j=1; j<tot; j++)
                {
                    if(SegmentProperIntersection(L[tot].x,L[tot].y,L[j].x,L[j].y)||
                            OnSegment(L[tot].x,L[j].x,L[j].y)||OnSegment(L[tot].y,L[j].x,L[j].y)||
                            check(L[tot].x,L[j].x,L[j].y)||check(L[tot].y,L[j].x,L[j].y))
                    {
                        //cout<<tot<<" "<<j<<endl;
                        int xx=Find(tot),yy=Find(j);
                        if(xx!=yy)
                        {
                            Union(xx,yy);
                        }
                    }
                }
            }
            else
            {
                int k;
                scanf("%d",&k);
                printf("%d\n",w[Find(k)]);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值