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

Segment set

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


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
 
思路:对所有线段两两判断是否相交,然后并查集合并区间即可。
 
View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 const int MAX = 1005;
  9 
 10 struct point
 11 {
 12     double x,y;
 13 };
 14 
 15 struct node
 16 {
 17     point st,ed;
 18 };
 19 
 20 struct Fater
 21 {
 22     int fat,size;
 23 };
 24 
 25 Fater father[MAX];
 26 node seg[MAX];
 27 int N;
 28 
 29 int find(int x)
 30 {
 31     if(x != father[x].fat)
 32         father[x].fat = find(father[x].fat);
 33     return father[x].fat;
 34 }
 35 
 36 double mul(point p2,point p1,point p0)
 37 {
 38     return ((p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y));
 39 }
 40 
 41 bool intersect(node s1,node s2)
 42 {
 43     if(min(s1.st.x,s1.ed.x)<=max(s2.st.x,s2.ed.x)&&
 44             min(s2.st.x,s2.ed.x)<=max(s1.st.x,s1.ed.x)&&
 45             min(s1.st.y,s1.ed.y)<=max(s2.st.y,s2.ed.y)&&
 46             min(s2.st.y,s2.ed.y)<=max(s1.st.y,s1.ed.y)&&
 47             mul(s2.st,s1.ed,s1.st)*mul(s1.ed,s2.ed,s1.st)>=0&&
 48             mul(s1.ed,s2.ed,s2.st)*mul(s2.ed,s1.st,s2.st)>=0)
 49         return true;
 50     return false;
 51 }
 52 
 53 int main()
 54 {
 55     int Case;
 56     scanf("%d",&Case);
 57     for(int ca=1; ca<=Case; ca++)
 58     {
 59         int Q;
 60         char oper;
 61         int idx = 1,which;
 62         for(int i=1; i<1001; i++)
 63         {
 64             father[i].fat = i;
 65             father[i].size = 1;
 66         }
 67         scanf("%d",&Q);
 68         getchar();
 69         while(Q--)
 70         {
 71             scanf("%c",&oper);
 72             if(oper == 'P')
 73             {
 74                 scanf("%lf%lf%lf%lf",&seg[idx].st.x,&seg[idx].st.y,&seg[idx].ed.x,&seg[idx].ed.y);
 75                 for(int i=idx-1; i>=1; i--)
 76                 {
 77                     if(intersect(seg[idx],seg[i]))
 78                     {
 79                         int t1 = find(i);
 80                         int t2 = find(idx);
 81                         if(t1 != t2)
 82                         {
 83                             father[t2].size += father[t1].size;
 84                             father[t1].fat = t2;
 85                         }
 86                     }
 87                 }
 88                 idx ++;
 89             }
 90             else
 91             {
 92                 scanf("%d",&which);
 93                 int ans = find(which);
 94                 printf("%d\n",father[ans].size);
 95             }
 96             getchar();
 97         }
 98         if(ca != Case)
 99             printf("\n");
100     }
101     return 0;
102 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值