hdu 1558 线段相交+并查集路径压缩

Segment set

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3457    Accepted Submission(s): 1290

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.

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

Author

LL

Source

HDU 2006-12 Programming Contest

题目大意:有n个指令,p加入一条线段,q查询id线段所在集合(两线段有交点为同一集合)的元素个数。

思路:用并查集路径压缩记录各个线段间的关系,根据叉积的定义有:Cross(v,w)=0时w在v上,>0时w在v上方,<0时w在v下方。

两线段有交点的必要条件:必须每条线段的两个端点在另一线段的两侧或直线上。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6
 7 const double eps=1e-8;
 8 const int maxn=1005;
 9 int f[maxn];
10 struct Point
11 {
12     double x,y;
13     Point(){}
14     Point(double x,double y):x(x),y(y){}
15 };
16 struct Line
17 {
18     Point a,b;
19 }L[maxn];
20 typedef Point Vector;
21 Vector operator -(Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);}
22 int dcmp(double x)
23 {
24     if(fabs(x)<eps) return 0;
25     else return x<0?-1:1;
26 }
27 double Cross(Vector A,Vector B){ return A.x*B.y-A.y*B.x;}//叉积
28
29 bool judge(Line a,Line b)//Cross(v,w)=0时w在v上,>0时w在v上方,<0时w在v下方
30 {
31     if(dcmp(Cross(a.a-b.a,b.b-b.a)*Cross(a.b-b.a,b.b-b.a))<=0
32         &&dcmp(Cross(b.a-a.a,a.b-a.a)*Cross(b.b-a.a,a.b-a.a))<=0)
33         return true;
34     return false;
35 }
36 int findset(int x){return f[x]!=x?f[x]=findset(f[x]):x;}
37 void Union(int a,int b)
38 {
39     a=findset(a);b=findset(b);
40     if(a!=b) f[a]=b;
41 }
42 int main()
43 {
44     int t,n,i,j,id;
45     char op[5];
46     double x1,y1,x2,y2;
47     scanf("%d",&t);
48     while(t--)
49     {
50         scanf("%d",&n);
51         int cnt=0;
52         for(i=0;i<n;i++)
53         {
54             scanf("%s",op);
55             if(op[0]==‘P‘)
56             {
57                 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
58                 L[++cnt].a=Point(x1,y1);L[cnt].b=Point(x2,y2);
59                 f[cnt]=cnt;
60                 for(j=1;j<=cnt-1;j++)
61                     if(judge(L[cnt],L[j]))
62                         Union(j,cnt);
63             }
64             else
65             {
66                 int ans=0;scanf("%d",&id);
67                 id=findset(id);
68                 for(j=1;j<=cnt;j++)
69                     if(findset(j)==id)
70                         ans++;
71                 printf("%d\n",ans);
72             }
73         }
74         if(t) printf("\n");
75     }
76     return 0;
77 }
时间: 2024-10-03 13:46:10

hdu 1558 线段相交+并查集路径压缩的相关文章

hdu 1558 (线段相交+并查集) Segment set

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐标,当输入Q的时候输入n,然后输出与第n条线段相交的线段有多少条 首先判断线段是否相交,在算法导论p577上有介绍 线段A(x1,y1)-B(x2,y2),所在直线L1方程为F1(x,y)=0;线段C(x3,y3)-D(x4,y4),所在直线L2方程为F2(x,y)=0; 如何判断两条线段有交点:(

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 #def

hdu 1558 Segment set (并查集)

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3907    Accepted Submission(s): 1471 Problem Description A segment and all segments which are connected with it compose a segment set

poj 1127 Jack Straws 线段相交+并查集

题意: 有n个木棍,给出木棍的两个端点的x,y坐标,判断其中某两个线段是否连通(可通过其他线段连通) #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queue> #include <map> #include <

hdu 1558 Segment set (并查集+计算几何)

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3486    Accepted Submission(s): 1297 Problem Description A segment and all segments which are connected with it compose a segment set

poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are

HDU 3635 Dragon Balls(并查集--路径压缩拓展应用)

题目大意: 初始时,有n个龙珠,编号从1到n,分别对应的放在编号从1到n的城市中. 现在又2种操作: T A B,表示把A球所在城市全部的龙珠全部转移到B城市.(第一次时,因为A球所在的城市只有一个球,所以只移动1个,如果有多个,则全部移动). Q A,表示查询A.要求得到的信息分别是:A现在所在的城市,A所在城市的龙珠数目,A转移到该城市移动的次数(如果没有移动就输出0) 思路:并查集,难点在于求龙珠的转移次数,可以在路径压缩的过程中沿着递归路径累加. //Accepted 1740 KB 5

poj1127 Jack Straws(线段相交+并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Jack Straws Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3512   Accepted: 1601 Description In the game of Jack Straws, a number of plastic or wooden "straws" are dumped o

并查集 路径压缩(具体解释)

拿HDU 1232举例. 题解: 首先在地图上给你若干个城镇.这些城镇都能够看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比方任意给你两个点,让你推断它们是否连通,或者问你整幅图一共同拥有几个连通分支,也就是被分成了几个互相独立的块.像畅通project这题,问还须要修几条路.实质就是求有几个连通分支.假设是1个连通分支,说明整幅图上的点都连起来了,不用再修路了.假设是2个连通分支,则仅仅要再修1条路,从两个分支中各选一个点,把它们连起来,那么全部的点都是