HDU HDU1558 Segment set(并查集+判断线段相交)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558

解题报告:首先如果两条线段有交点的话,这两条线段在一个集合内,如果a跟b在一个集合内,b跟c在一个集合内,那么a跟c在一个集合内。在一个平面上,有两种操作:

P:在这个平面上添加一条线段

Q k:询问添加的第k条线段所在的那个集合有多少条线段

用并查集,然后就是要判断一下线段有没有交点。还有就是题目要求两个test之间要有空行,为此我还PE了一次。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 const int maxn = 1005;
  8 const double eps = 1e-6;
  9 struct point
 10 {
 11     double x,y;
 12     point(double x = 0,double y = 0):x(x),y(y) {}
 13     inline friend point operator + (point p1,point p2)
 14     {
 15         return point(p1.x+p2.x,p1.y+p2.y);
 16     }
 17     inline friend point operator - (point p1,point p2)
 18     {
 19         return point(p1.x-p2.x,p1.y-p2.y);
 20     }
 21 }pos[maxn];
 22 struct line
 23 {
 24     point s,e;
 25     int flag;
 26 }L[maxn];
 27 int pre[maxn];
 28 int find(int d)
 29 {
 30     return pre[d] == d? d:pre[d] = find(pre[d]);
 31 }
 32 inline double dot(point p1,point p2)    //求叉积
 33 {
 34     return p1.x*p2.y - p2.x*p1.y;
 35 }
 36 int judge(point p1,point p2,point p3,point p4)    //判断线段没有没交点
 37 {
 38     double temp1 = dot(p1-p3,p4-p3) * dot(p2-p3,p4-p3);
 39     double temp2 = dot(p3-p1,p2-p1) * dot(p4-p1,p2-p1);
 40     if((temp1 < 0 || fabs(temp1) < eps) && (temp2 < 0 || fabs(temp2) < eps)) return 1;
 41     return 0;
 42 }
 43 int T,n,m;
 44 void push(line t,line* L,int m)
 45 {
 46     for(int i = 1;i < m;++i)
 47     if(judge(L[i].s,L[i].e,t.s,t.e))
 48     {
 49         pre[find(t.flag)] = find(L[i].flag);
 50     //    break;
 51     }
 52     L[m] = t;
 53 }
 54 int query(int k)
 55 {
 56     int temp = find(k),ans = 0;
 57     for(int i = 1;i <= m;++i)
 58     if(find(i) == temp)
 59     ans++;
 60     return ans;
 61 }
 62 int main()
 63 {
 64 //    freopen("in","r",stdin);
 65     double x1,y1,x2,y2;
 66     scanf("%d",&T);
 67     for(int l = 0;l < T;++l)
 68     {
 69         if(l) puts("");
 70         scanf("%d",&n);
 71         for(int i = 0;i <= 1000;++i)  //初始化并查集
 72         pre[i] = i;
 73         char oper[5];
 74         m = 0;   //初始化当前线段的数量
 75         while(n--)
 76         {
 77             scanf("%s",oper);
 78             if(oper[0] == ‘P‘)
 79             {
 80                 line temp;
 81                 scanf("%lf%lf%lf%lf",&temp.s.x,&temp.s.y,&temp.e.x,&temp.e.y);
 82                 temp.flag = ++m;
 83                 push(temp,L,m);
 84             }
 85             else if(oper[0] == ‘Q‘)
 86             {
 87                 int k;
 88                 scanf("%d",&k);
 89                 printf("%d\n",query(k));
 90             }
 91         }
 92 //        for(int i = 1;i <= m;++i)
 93 //        {
 94 //            for(int j = 1;j <= m;++j)
 95 //            printf(judge(L[i].s,L[i].e,L[j].s,L[j].e)? "1 ":"0 ");
 96 //            printf("\n");
 97 //        }
 98     }
 99     return 0;
100 }

时间: 2024-08-20 23:08:35

HDU HDU1558 Segment set(并查集+判断线段相交)的相关文章

HDU1558 - Segment set 并查集 + 判断线段相交

HDU1558 - Segment set: http://acm.hdu.edu.cn/showproblem.php?pid=1558 题目大意: 输入一些线段的端点坐标,若两线段相交,则把他们合并成一个集合,输入数据里会有k,问和k线段相交的线段的数目(包括自己) 思路: 每次输入一条线段,都从头扫描一次. 找出之前输入的线段里面,所有和其相交的线段,并且合并(合并用的是线段的ID). 就是: 并查集 + 判断线段相交 代码: #include <iostream> #include &

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

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

hdu 1558 Segment set(并查集+判断线段是否相交)

代码: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int father[1005]; int son_cnt[1005]; char s[5]; //int cnt; struct point { double x,y; }; point a[1005],b[1005]; int find_father(int x) { int r=x; while(fathe

URAL - 1966 - Cycling Roads(并查集 + 判线段相交)

题意:n 个点,m 条边(1 ≤ m < n ≤ 200),问所有点是否连通(两条边相交,则该 4 点连通). 题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1966 -->>对于每条边,边上的两端点并入集合,枚举边与边,判断他们是否相交,是的话各点并入集合,最后看集合内元素的个数是否为n.. #include <cstdio> #include <cmath> const int MAXN = 200

hdu 5424 回溯+并查集判断连通性

题意:给定一个n个点n条边的无向图,判断是否存在哈密顿路径. 思路:先用并查集判断图是否连通,然后从度数最小的点开始回溯,看是否能找到一条哈密顿路径. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <set> 5 using namespace std; 6 7 const int INF = 999999; 8 const int N = 1001; 9

HDU Catch (二分图判断奇环+并查集判断联通)

Problem Description A thief is running away!We can consider the city where he locates as an undirected graph in which nodes stand for crosses and edges stand for streets. The crosses are labeled from 0 to N–1. The tricky thief starts his escaping fro

hdu 1811Rank of Tetris (并查集 + 拓扑排序)

1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B. 3 4 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK". 5 否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出&quo

HDOJ Ice_cream&#39;s world I 2120【并查集判断成环】

Ice_cream's world I Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 848    Accepted Submission(s): 494 Problem Description ice_cream's world is a rich country, it has many fertile lands. Today,