HDU 1558 Segment set(判断线段相交+并查集)

判断线段相交和并查集,两种简单算法的综合题。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<fstream>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<queue>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
using namespace std;
const int maxn=100005,inf=1<<29;
int dir[][2]={ {0,1},{-1,0},{0,-1},{1,0},{-1,1},{-1,-1},{1,-1},{1,1}};
int n,m,t,fa[maxn],num[maxn];
double EPS=1e-10;
double add(double a,double b)
{
    if(abs(a+b)<EPS*(abs(a)+abs(b))) return 0;
    return a+b;
}
struct P
{
    double x,y;
    P(){}
    P(double x,double y):x(x),y(y){}
    P operator +(P p)
    {
        return P(add(x,p.x),add(y,p.y));
    }
    P operator -(P p)
    {
        return P(add(x,-p.x),add(y,-p.y));
    }
    P operator *(double d)
    {
        return P(x*d,y*d);
    }
    double dot(P p)//内积
    {
        return add(x*p.x,y*p.y);
    }
    double det(P p)//外积
    {
        return add(x*p.y,-p.x*y);
    }
};
struct v
{
    P p,q;
}a[maxn];
bool on_seg(P p1,P p2,P q)//判断点q是否在线段p1p2上
{
    return (p1-q).det(p2-q)==0&&(p1-q).dot(p2-q)<=0;
}
P intersection(P p1,P p2,P q1,P q2)//计算两线段的交点
{
    return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
bool judge(v s1,v s2)
{
    if((s1.p-s1.q).det(s2.p-s2.q)==0)
    {
        return on_seg(s1.p,s1.q,s2.p)||
                    on_seg(s1.p,s1.q,s2.q)||
                    on_seg(s2.p,s2.q,s1.p)||
                    on_seg(s2.p,s2.q,s1.q);
    }
    else
    {
        P r=intersection(s1.p,s1.q,s2.p,s2.q);
        //cout<<"x = "<<r.x<<" y= "<<r.y<<endl;
        return on_seg(s1.p,s1.q,r)&&on_seg(s2.p,s2.q,r);
    }
}
int Find(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=Find(fa[x]);
}

void Merge(int x,int y)
{
    x=Find(x);
    y=Find(y);
    if(x!=y) fa[y]=x,num[x]+=num[y];
}

int main()
{
    //freopen("1558in.txt","r",stdin);
    cin>>t;
    v s1,s2;
    while(t--)
    {
        cin>>n;
        int cnt=1;
        for(int i=0;i<maxn;i++) fa[i]=i,num[i]=1;
        while(n--)
        {
            char op;
            cin>>op;
            if(op=='P')
            {
                cin>>a[cnt].p.x>>a[cnt].p.y>>a[cnt].q.x>>a[cnt].q.y;
                for(int i=1;i<cnt;i++)
                    if(judge(a[i],a[cnt])) Merge(i,cnt);
                cnt++;
            }
            else
            {
                int y;
                cin>>y;
                y=Find(y);
                cout<<num[y]<<endl;
            }
        }
        if(t) cout<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值