HDU 1558 Segment set

来源:互联网 发布:mac双系统os系统消失 编辑:程序博客网 时间:2024/06/06 11:41

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558

题目大意:询问与某条线段相交的线段有多少条,间接的也算。

算法分析,关键是求线段交点,如能判断线段是否相交,用并查集维护每个集合的个数就行了。

对于判断线段是否相交

这里并没有采用快速排斥+跨立实验,原因是采用那个不能求出线段交点。这里采用的方法是求出线段交点,然后判断交点是否都在两条线段上。

求交点注意设置精度,否则必然WA。

具体分析过程请参考《挑战程序设计竞赛》计算几何那章的内容,说得很详细,此处不再赘述。

下面是AC代码:

#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 | 1using namespace std;const int maxn=1005,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(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(){    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
原创粉丝点击