首页 > 代码库 > 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 线段相交+并查集
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。