HDU1558 Segment set(计算几何+并查集)

时间:2023-02-10 19:20:34

题意:给你一些线段,问与第i根线段相交的线段有几根。。

思路:计算几何+并查集

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

using namespace std;
const int N = 1009;
const double INF = 1e20 , EPS = 1E-6;
bool zero(double x){
    return -EPS<x&&x<EPS;
}
struct cvector{
    double x,y;
    cvector(){};
    cvector(double a,double b){x=a,y=b;}
};
double operator^(cvector p,cvector q){
    return p.x*q.y-q.x*p.y;
}
double operator *(cvector p,cvector q){
    return p.x*q.x+p.y*q.y;
}
struct cpoint{
    double x,y;
    cpoint(double a,double b){
        x = a,y = b;
    }
    cpoint(){}
};
cvector operator -(cpoint a, cpoint b){   ///向量ab
    return cvector(b.x-a.x, b.y-a.y);
}
struct cline{
    cpoint a,b;
} re[N];

bool dots_inline(cpoint p1,cpoint p2,cpoint p3){///判三点共线
return zero((p2-p1)^(p3-p1));
}
bool same_side(cpoint p1,cpoint p2,cline l){  ///两点在线段同侧
    cvector v0=l.b-l.a;
    cvector v1=p1-l.a,v2=p2-l.a;
    return (v1^v0)*(v2^v0)>EPS;
}

bool dot_onseg(cpoint p,cline ll){    /// 点在线段上
    if(!dots_inline(p,ll.a,ll.b)) return false;
    cvector v1=ll.b-ll.a,v2=p-ll.a;
    cvector v3=ll.a-ll.b,v4=p-ll.b;
    if(v1*v2>-EPS&&v3*v4>-EPS) return true;
    return false;
}
bool intersect_in(cline u,cline v){   ///线段相交,包括交点和重合
    if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
        return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
    return dot_onseg(u.a,v)||dot_onseg(u.b,v)
    ||dot_onseg(v.a,u)||dot_onseg(v.b,u);
}
int fa[N];
int finfa(int k)
{
    if(fa[k]==k) return k;
    return fa[k] = finfa(fa[k]);
}
void un(int a,int b)
{
    fa[finfa(a)] = fa[finfa(b)];
}

bool xx(int a,int b)
{
    return intersect_in(re[a],re[b]);
}
int main()
{
    freopen("in.txt","r",stdin);
    int cas,ou=0,n,tmp,cnt;
    char ar[3];
    cpoint a,b;
    scanf("%d",&cas);
    while(cas--)
    {
        cnt = 0;
        if(ou) printf("\n");ou = true;
        scanf("%d",&n);
        for(int i=0;i<=n;i++) fa[i] = i;
        while(n--)
        {
            scanf("%s",ar);
            if(ar[0]=='P')
            {
                scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
                re[cnt].a=a,re[cnt].b=b;
                for(int i=0;i<cnt;i++)
                {
                    if(finfa(i)!=finfa(cnt)&&xx(i,cnt))
                    {
                        un(i,cnt);
                    }
                }cnt++;
            }
            else
            {
                scanf("%d",&tmp);tmp--;
                //cout<<tmp<<" "<<cnt<<endl;
                int f = finfa(tmp),ans = 0;
                for(int i=0;i<cnt;i++)
                if(finfa(i)==f) ans++;
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}