hdu 1558 Segment set【基础带权并查集+计算几何】

Segment set

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3599    Accepted Submission(s): 1346

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

分析:这道题是道基础带权并查集的题,主要就是如何判断两条线段相交(注意:是线段)

有一个链接:http://blog.csdn.net/rickliuxiao/article/details/6259322

为了确定两条线段是否相交,要检查每个线段是否跨越了包含另一线段的直线。 给定一个线段p1p2,如果点p1位于某一直线的一边, 而点p2位于直线的另一边,则称线段p1p2跨越了该直线。如果p1和p2 就落在该直线的话,即出现边界情况。两条线段相交, 当且仅当下面两个条件中有一个成立,或同时成立:

1)每个线段都跨越包含了另一线段的直线。

2)一个线段的某一端点位于另一线段上。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #include<iostream>
  5. #define Min(a,b) a<b?a:b
  6. #define Max(a,b) a>b?a:b
  7. #define maxh 1000+10
  8. using namespace std;
  9. typedef struct{
  10.     double x,y;
  11. }point;
  12. typedef struct{
  13.     point p0,p1;
  14. }node;
  15. node E[maxh];
  16. int set[maxh],rank[maxh];
  17. void init(){
  18.     for(int i=0;i<maxh;i++){
  19.         set[i]=i,rank[i]=1;
  20.     }
  21. }
  22. int findx(int x){
  23.     if(x==set[x])
  24.     return x;
  25.     set[x]=findx(set[x]);
  26.     return set[x];
  27. }
  28. void Union(int x,int y){
  29.     x=findx(x);
  30.     y=findx(y);
  31.     if(x!=y){
  32.         set[x]=y;
  33.         rank[y]+=rank[x];
  34.     }
  35. }
  36. double direction(point p0,point p1,point p2){
  37.     return ((p2.x-p0.x)*(p1.y-p0.y)-(p1.x-p0.x)*(p2.y-p0.y));
  38. }
  39. bool on(point p0,point p1,point p2){
  40.     double xmin,ymin,xmax,ymax;
  41.     xmin=Min(p0.x,p1.x);
  42.     xmax=Max(p0.x,p1.x);
  43.     ymin=Min(p0.y,p1.y);
  44.     ymax=Max(p0.y,p1.y);
  45.     if(p2.x>=xmin&&p2.x<=xmax&&p2.y>=ymin&&p2.y<=ymax)
  46.     return true;
  47.     return false;
  48. }
  49. bool intersect(point p0,point p1,point p2,point p3){
  50.     double d0,d1,d2,d3;
  51.     d0=direction(p2,p3,p0);
  52.     d1=direction(p2,p3,p1);
  53.     d2=direction(p0,p1,p2);
  54.     d3=direction(p0,p1,p3);
  55.   //  printf("%lf %lf %lf %lf\n",d0,d1,d2,d3);
  56.     if(((d0<0&&d1>0)||(d0>0&&d1<0))&&((d2>0&&d3<0)||(d2<0&&d3>0))){
  57.     //    printf("cwefg");
  58.     return true;
  59.     }
  60.     else if(d0==0&&on(p2,p3,p0))
  61.     return true;
  62.     else if(d1==0&&on(p2,p3,p1))
  63.     return true;
  64.     else if(d2==0&&on(p0,p1,p2))
  65.     return true;
  66.     else if(d3==0&&on(p0,p1,p3))
  67.     return true;
  68.     else
  69.     return false;
  70. }
  71. int main(){
  72.     int T,n,h,x;
  73.     char c[2];
  74.     scanf("%d",&T);
  75.     while(T--){
  76.         scanf("%d",&n);
  77.         init();
  78.         h=1;
  79.         while(n--){
  80.             scanf("%s",c);
  81.             if(c[0]==‘P‘){
  82.                 scanf("%lf%lf%lf%lf",&E[h].p0.x,&E[h].p0.y,&E[h].p1.x,&E[h].p1.y);
  83.                 for(int i=1;i<h;i++){
  84.                     if(intersect(E[i].p0,E[i].p1,E[h].p0,E[h].p1)){
  85.                    //     printf("<%d,%d>\n",i,h);
  86.                         Union(i,h);
  87.                     }
  88.                 }
  89.                 h++;
  90.             }
  91.             else{
  92.                 scanf("%d",&x);
  93.                 printf("%d\n",rank[findx(x)]);
  94.             }
  95.         }
  96.         if(T){
  97.             printf("\n");
  98.         }
  99.     }
  100.     return 0;
  101. }
  102.                     
  103.     
时间: 2024-10-05 04:27:45

hdu 1558 Segment set【基础带权并查集+计算几何】的相关文章

hdu 2818 Building Block【基础带权并查集】

Building Block Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3365    Accepted Submission(s): 1009 Problem Description John are playing with blocks. There are N blocks (1 <= N <= 30000) numbe

hdu 3635 Dragon Balls 【基础带权并查集】

Dragon Balls Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3461    Accepted Submission(s): 1348 Problem Description Five hundred years later, the number of dragon balls will increase unexpect

HDU 2818 Building Block(带权并查集)

[题目链接]:Click here~~ [题意]: 给 n 块砖头,开始各为一堆,两种操作: 1.把 X 所在的那一堆箱子里的砖头放到 Y 所在的那一堆上面. 2.询问 X 下面有多少块砖. [解题思路]:好像大家都叫它带权并查集,那为了方便,这里也这样叫吧,因为涉及前面的和后面的箱子个数,对应的查找操作,一开始想用结构体来写,在结构体里定义每个箱子的前驱和后继,每次输入的时候统计一下相应的前驱和后继的个数,后来发现不行,因为涉及到合并操作,比如说M 2 4 M 2 6连续出现两个2,用结构体是

hdu 3074 Zjnu Stadium (带权并查集)

Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1744    Accepted Submission(s): 660 Problem Description In 12th Zhejiang College Students Games 2007, there was a new stadium built i

HDU(1856),裸的带权并查集

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1856 题意:朋友圈问题,A和B是朋友,B和C是朋友则A和C也是朋友,依次类推,题目的意思就是求最大的朋友圈,即求最大集合中元素的个数.裸的并查集加个秩数组就行了. #include <stdio.h> int father[100050]; int rank[100050]; int Find_Set (int x) { if(x!=father[x]) father[x] = Find_Set(

hdu 3047 Zjnu Stadium【带权并查集】

In 12th Zhejiang College Students Games 2007, there was a new stadium built in Zhejiang Normal University. It was a modern stadium which could hold thousands of people. The audience Seats made a circle. The total number of columns were 300 numbered 1

HDU 3047 Zjnu Stadium(带权并查集,难想到)

M - Zjnu Stadium Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description In 12th Zhejiang College Students Games 2007, there was a new stadium built in Zhejiang Normal University. It was a modern stadium

HDU 3047 Zjnu Stadium 带权并查集

题目来源:HDU 3047 Zjnu Stadium 题意:给你一些人 然后每次输入a b c 表示b在距离a的右边c处 求有多少个矛盾的情况 思路:用sum[a] 代表a点距离根的距离 每次合并时如果根一样 判断sum数组是否符合情况 根不一样 合并两棵树 这里就是带权并查集的精髓 sum[y] = sum[a]-sum[b]+x 这里y的没有合并前b的根 #include <cstdio> #include <cstring> using namespace std; cons

HDU - 3038 How Many Answers Are Wrong (带权并查集)

题意:n个数,m次询问,每次问区间a到b之间的和为s,问有几次冲突 思路:带权并查集的应用,[a, b]和为s,所以a-1与b就可以确定一次关系,通过计算与根的距离可以判断出询问的正确性 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 200010; int f[MAXN],a