首页 > 代码库 > hdu 1558 线段相交+并查集

hdu 1558 线段相交+并查集

题意:要求相交的线段都要塞进同一个集合里

 

sol:并查集+判断线段相交即可。n很小所以n^2就可以水过

  1 #include <iostream>  2 #include <cmath>  3 #include <cstring>  4 #include <cstdio>  5 using namespace std;  6   7 int f[1010];  8 char ch;  9 int tmp,n; 10 double X1,X2,Y1,Y2; 11  12    #define eps 1e-8 13    #define PI acos(-1.0)//3.14159265358979323846 14    //判断一个数是否为0,是则返回true,否则返回false 15    #define zero(x)(((x)>0?(x):-(x))<eps) 16    //返回一个数的符号,正数返回1,负数返回2,否则返回0 17    #define _sign(x)((x)>eps?1:((x)<-eps?2:0)) 18   struct point 19   { 20       double x,y; 21       point(){} 22       point(double xx,double yy):x(xx),y(yy) 23       {} 24   }; 25   struct line 26   { 27       point a,b; 28       line(){}      //默认构造函数 29       line(point ax,point bx):a(ax),b(bx) 30       {} 31   }l[1010];//直线通过的两个点,而不是一般式的三个系数 32  33    //求矢量[p0,p1],[p0,p2]的叉积 34    //p0是顶点 35    //若结果等于0,则这三点共线 36    //若结果大于0,则p0p2在p0p1的逆时针方向 37    //若结果小于0,则p0p2在p0p1的顺时针方向 38    double xmult(point p1,point p2,point p0) 39    { 40        return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 41    } 42    //计算dotproduct(P1-P0).(P2-P0) 43    double dmult(point p1,point p2,point p0) 44    { 45        return(p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y); 46    } 47    //两点距离 48    double distance(point p1,point p2) 49    { 50        return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); 51    } 52    //判三点共线 53    int dots_inline(point p1,point p2,point p3) 54    { 55        return zero(xmult(p1,p2,p3)); 56    } 57    //判点是否在线段上,包括端点 58    int dot_online_in(point p,line l) 59    { 60        return zero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps; 61    } 62    //判点是否在线段上,不包括端点 63    int dot_online_ex(point p,line l) 64    { 65        return dot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y)); 66    } 67    //判两点在线段同侧,点在线段上返回0 68    int same_side(point p1,point p2,line l) 69    { 70        return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps; 71    } 72    //判两点在线段异侧,点在线段上返回0 73    int opposite_side(point p1,point p2,line l) 74    { 75        return xmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps; 76    } 77    //判两直线平行 78    int parallel(line u,line v) 79    { 80        return zero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y)); 81    } 82    //判两直线垂直 83    int perpendicular(line u,line v) 84    { 85        return zero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y)); 86    } 87    //判两线段相交,包括端点和部分重合 88    int intersect_in(line u,line v) 89    { 90        if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b)) 91            return!same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u); 92        return dot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u); 93    } 94 int find(int x) 95 { 96     if (f[x]!=x) 97         f[x]=find(f[x]); 98     return f[x]; 99 }100 101 void iunion(int x,int y)102 {103     int fx,fy;104     fx=find(x);105     fy=find(y);106     if (fx!=fy)107         f[fx]=fy;108 }109 110 int main()111 {112     //freopen("in.txt","r",stdin);113     int times;114     cin>>times;115     while(times--)116     {117 118     cin>>n;119     int T=0;120     for (int i=1;i<=n;i++)121     {122         /*123         cout<<"dev: ";124         for (int j=1;j<=T;j++)125             cout<<f[j]<<" ";126         cout<<endl;127         */128         cin>>ch;129         if (ch==Q)130         {131             cin>>tmp;132             int ans=0;133             for (int j=1;j<=T;j++)134                 if (find(tmp)==find(j))     ans++;135             cout<<ans<<endl;136         }137         else if (ch==P)138         {139             cin>>X1>>Y1>>X2>>Y2;140             T++;141             f[T]=T;142             l[T]=line(point(X1,Y1),point(X2,Y2));143             //cout<<l[T].a.x<<" "<<l[T].a.y<<" "<<l[T].b.x<<" "<<l[T].b.y<<endl;144             for (int j=1;j<T;j++)145                 if (intersect_in(l[T],l[j])>0)146                     iunion(j,T);147         }148     }149 150     if (times>0)151         cout<<endl;152     }153     return 0;154 }

 

hdu 1558 线段相交+并查集