hdu1558 Segment set
Problem Description
A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some segment set.
Input
In the first line there is an integer t - the number of test case. For each test case in first line there is an integer n (n<=1000) - the number of commands.
There are two different commands described in different format shown below:
P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).
Q k - query the size of the segment set which contains the k-th segment.
k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.
There are two different commands described in different format shown below:
P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).
Q k - query the size of the segment set which contains the k-th segment.
k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.
Output
For each Q-command, output the answer. There is a blank line between test cases.
Sample Input
1
10
P 1.00 1.00 4.00 2.00
P 1.00 -2.00 8.00 4.00
Q 1
P 2.00 3.00 3.00 1.00
Q 1
Q 3
P 1.00 4.00 8.00 2.00
Q 2
P 3.00 3.00 6.00 -2.00
Q 5
Sample Output
1
2
2
2
5
这题可以用并查集做,主要是要判断两条线段是不是相交,我的方法是记两条线段的端点是p1(x1,y1),p2(x2,y2)以及p3(x3,y3),p4(x4,y4),分别看4个端点有没有在另一条线段上,如果有,那么相交,如果没有,那么再用叉积判断每条线段的两个端点是不是在另一条线段的两边,如果p1,p2在线段p3p4的两边而且p3,p4在线段p1p2的两边,那么p1p2和p3p4相交,否则不相交。那么怎么判断p1,p2是否在线段p3p4的两边呢,这里用到了叉积,第一次取p1,p3,p4,如果向量p1p3和向量p1p4的叉积是正的,那么p1p2在p3p4的顺时针方向,反之在逆时针方向。再取p2,p3,p4,方法相同,如果两个叉积符号不同,那么p1,p2在线段p3p4的两边,否则不在。
#include<stdio.h> #include<string.h> #include<math.h> int pre[1006]; int find(int x){ int r=x; while(r!=pre[r])r=pre[r]; return r; } int shizhen(double x2,double y2,double x4,double y4,double x5,double y5){ double x=x4-x2,y=y4-y2,xx=x5-x2,yy=y5-y2; if(x*yy-xx*y>0)return 1; else return -1; } int xianshang(double x2,double y2,double x3,double y3,double x4,double y4){ if((x2-x3)*(y4-y2)-(y2-y3)*(x4-x2)!=0)return 0; if((x2<x3 && x2<x4) || (x2>x3 && x2>x4))return 0; return 1; } int panduan(double x2,double y2,double x3,double y3,double x4,double y4,double x5,double y5) { if(xianshang(x2,y2,x4,y4,x5,y5) || xianshang(x3,y3,x4,y4,x5,y5) || xianshang(x4,y4,x2,y2,x3,y3) || xianshang(x5,y5,x2,y2,x3,y3))return 1; if((shizhen(x2,y2,x4,y4,x5,y5)*shizhen(x3,y3,x4,y4,x5,y5)<0) && (shizhen(x4,y4,x2,y2,x3,y3)*shizhen(x5,y5,x2,y2,x3,y3)<0))return 1; return 0; } int main() { int T,n,m,i,j,a,t1,xianduan[1006],num[1005],num1,h; double x2[1006],x3[1006],y2[1006],y3[1006]; char s[10]; scanf("%d",&T); for(h=1;h<=T;h++) { scanf("%d",&n); num1=0; for(i=1;i<=n;i++){ pre[i]=i;num[i]=0; } for(i=1;i<=n;i++){ scanf("%s",s); if(s[0]=='P'){ num1++; scanf("%lf%lf%lf%lf",&x2[num1],&y2[num1],&x3[num1],&y3[num1]); num[num1]=1; for(j=1;j<=num1-1;j++){ if(panduan(x2[j],y2[j],x3[j],y3[j],x2[num1],y2[num1],x3[num1],y3[num1])){ t1=find(j); if(num1!=t1){ pre[t1]=num1;num[num1]+=num[t1]; } else continue; } //printf("%d ",panduan(x2[j],y2[j],x3[j],y3[j],x2[num1],y2[num1],x3[num1],y3[num1])); } //printf("\n"); } else if(s[0]=='Q'){ scanf("%d",&a); t1=find(a); printf("%d\n",num[t1]); } } if(h!=T)printf("\n"); /*for(i=1;i<=5;i++){ t1=find(i); printf("%d ",num[t1]); } printf("\n");*/ } return 0; }