首页 > 代码库 > HDU 1558 Segment set (并查集+线段非规范相交)

HDU 1558 Segment set (并查集+线段非规范相交)

题目链接

题意 : 如果两个线段相交就属于同一集合,查询某条线段所属集合有多少线段,输出。

思路 : 先判断与其他线段是否相交,然后合并。

  1 //1558  2 #include <cstdio>  3 #include <cstring>  4 #include <iostream>  5 #include <cmath>  6 #define eps 1e-8  7 #define zero(x) (((x) > 0 ? (x) : (-x)) < eps)  8   9 using namespace std ; 10  11 struct point 12 { 13     double x,y ; 14 } p[1010]; 15 struct Line 16 { 17     point a; 18     point b ; 19 //    int num ; 20 } L[1010] ; 21 int father[1010],numb[1010],rankk[1010] ; 22 int  cnt ; 23 double direction(point p0,point p1,point p2) 24 { 25     return (p2.x-p0.x)*(p1.y-p0.y)-(p1.x-p0.x)*(p2.y-p0.y); 26 } 27  28 bool on_segment(point p0,point p1,point p2) 29 { 30     if((min(p0.x,p1.x)<=p2.x && p2.x<=max(p0.x,p1.x)) && (min(p0.y,p1.y)<=p2.y && p2.y<=max(p0.y,p1.y))) 31         return true; 32     return false; 33 } 34  35 bool Segment_intersect(point p1,point p2,point p3,point p4) 36 { 37     double d1,d2,d3,d4; 38     d1 = direction(p3,p4,p1); 39     d2 = direction(p3,p4,p2); 40     d3 = direction(p1,p2,p3); 41     d4 = direction(p1,p2,p4); 42     if(((d1>0 && d2<0)||(d1<0 && d2>0)) && ((d3>0 && d4<0)||(d3<0&&d4>0))) 43         return true; 44     else if((d1==0 && on_segment(p3,p4,p1)) || (d2==0 && on_segment(p3,p4,p2)) || (d3==0 && on_segment(p1,p2,p3)) || (d4==0 && on_segment(p1,p2,p4))) 45         return true; 46     return false; 47 } 48 int find_(int x) 49 { 50     if(father[x] != x) 51         father[x] = find_(father[x]) ; 52     return father[x] ; 53 } 54  55 void mergee(int a, int b){ 56      int fx = find_(a); 57      int fy = find_(b); 58  59      if (fx != fy){ 60            father[fy] = fx; 61            numb[fx] += numb[fy]; 62      } 63 } 64 void Init() 65 { 66     cnt = 0 ; 67     for(int i=0; i<=1010; i++) 68     { 69         numb[i]=1; 70     } 71     for(int i = 0 ; i < 1010 ; i++) 72         father[i] = i ; 73     memset(rankk,0,sizeof(rankk)) ; 74 } 75 int main() 76 { 77     int T ,n,ss; 78     scanf("%d",&T) ; 79     char s[4] ; 80     while( T--) 81     { 82         scanf("%d",&n) ; 83         Init() ; 84         for(int i = 0 ; i < n ; i++) 85         { 86             scanf("%s",s) ; 87             if(s[0] == P) 88             { 89                 cnt ++ ; 90                 scanf("%lf %lf %lf %lf",&L[cnt].a.x,&L[cnt].a.y,&L[cnt].b.x,&L[cnt].b.y) ; 91                 for(int j = 1 ; j < cnt ; j ++) 92                     if(find_(j) != find_(cnt) && Segment_intersect(L[j].a,L[j].b,L[cnt].a,L[cnt].b)) 93                         mergee(j,cnt) ; 94             } 95             else 96             { 97                 scanf("%d",&ss) ; 98                 printf("%d\n",numb[find_(ss)]) ; 99             }100         }101         if(T) printf("\n") ;102     }103     return 0 ;104 }
View Code

线段非规范相交1

 1 double cross(point p0,point p1,point p2) 2 { 3     return (p2.x-p0.x)*(p1.y-p0.y)-(p1.x-p0.x)*(p2.y-p0.y); 4 } 5  6 bool on_segment(point p0,point p1,point p2) 7 { 8     if((min(p0.x,p1.x)<=p2.x && p2.x<=max(p0.x,p1.x)) && (min(p0.y,p1.y)<=p2.y && p2.y<=max(p0.y,p1.y))) 9         return true;10     return false;11 }12 13 bool Segment_intersect(point p1,point p2,point p3,point p4)14 {15     double d1,d2,d3,d4;16     d1 = cross(p3,p4,p1);17     d2 = cross(p3,p4,p2);18     d3 = cross(p1,p2,p3);19     d4 = cross(p1,p2,p4);20     if(((d1>0 && d2<0)||(d1<0 && d2>0)) && ((d3>0 && d4<0)||(d3<0&&d4>0)))21         return true;22     else if((d1==0 && on_segment(p3,p4,p1)) || (d2==0 && on_segment(p3,p4,p2)) || (d3==0 && on_segment(p1,p2,p3)) || (d4==0 && on_segment(p1,p2,p4)))23         return true;24     return false;25 }
View Code

 

线段非规范相交2

 1 double cross(point a, point b, point c) 2 { 3     return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y); 4 } 5  6 //aa, bb为一条线段两端点 cc, dd为另一条线段的两端点 相交返回true, 不相交返回false 7 bool intersect(point aa, point bb, point cc, point dd) 8 { 9     if ( max(aa.x, bb.x)<min(cc.x, dd.x) )10     {11         return false;12     }13     if ( max(aa.y, bb.y)<min(cc.y, dd.y) )14     {15         return false;16     }17     if ( max(cc.x, dd.x)<min(aa.x, bb.x) )18     {19         return false;20     }21     if ( max(cc.y, dd.y)<min(aa.y, bb.y) )22     {23         return false;24     }25     if ( cross(cc, bb, aa)*cross(bb, dd, aa)<0 )26     {27         return false;28     }29     if ( cross(aa, dd, cc)*cross(dd, bb, cc)<0 )30     {31         return false;32     }33     return true;34 }
View Code