hdu1558线段相交与并查集
2015-06-16 01:50
204 查看
小吐嘈:第一次写这种计算几何的东西,被坑的莫明奇妙,最后才发现,不是自己的函数写错了,而是在读入的时候用llf去读数据,然后就WA的莫明奇妙。double 用%lf,long double 才是%llf呀,实在是不用不知道,一用就吓一跳。然后,输入的时候,又是那个格式呀,真的是什么鬼。然后,对于double 型的变量,在比较的时候都是不精确比较,必须要指定一个精度才可以。可两个double的差小于这个精度的时候,我们就可以认为他们相等了(想想微积分的
语言吧)
言归正传,先看题意:
给你一系列线段,如果两个线段相交就将它们归为一类,要求某个线段所在的类有多少根线段。
既然有集合的相并那么就毫不犹豫的使用并查集啦。
然而,这里的重点其实是就是判断线段相交。
如何判断线段相交呢?
相交又分为普通相交和有端点在另一个线段上。
首先复习下线性代数叉积的知识。
>0时,向量P在向量Q在顺时针。
<0向量P在向量Q在逆时针。
对于AB与CD相交的一般情况(中间那个情况)
我们可以发现向量CA与向量CB在向量CD的两侧,同时,向量CA和向量DA也要在AB在两侧(这两个两侧要同时满足才行,不然,又如右边那个反例,只满足CA CB 在CD的两侧,但是不满足CA,DA在AB在两侧)。
而对于其中有一个线段上的一个端点在另一条线段的线段的情况(比如左图),发现AC叉乘BC为0,因此可以这么判断是否有点共线。
以下是代码:
语言吧)
言归正传,先看题意:
给你一系列线段,如果两个线段相交就将它们归为一类,要求某个线段所在的类有多少根线段。
既然有集合的相并那么就毫不犹豫的使用并查集啦。
然而,这里的重点其实是就是判断线段相交。
如何判断线段相交呢?
相交又分为普通相交和有端点在另一个线段上。
首先复习下线性代数叉积的知识。
>0时,向量P在向量Q在顺时针。
<0向量P在向量Q在逆时针。
对于AB与CD相交的一般情况(中间那个情况)
我们可以发现向量CA与向量CB在向量CD的两侧,同时,向量CA和向量DA也要在AB在两侧(这两个两侧要同时满足才行,不然,又如右边那个反例,只满足CA CB 在CD的两侧,但是不满足CA,DA在AB在两侧)。
而对于其中有一个线段上的一个端点在另一条线段的线段的情况(比如左图),发现AC叉乘BC为0,因此可以这么判断是否有点共线。
以下是代码:
[code]#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <math.h> #include <limits.h> #include <queue> #include <stack> #include <vector> #define N 1010 using namespace std; struct Set { int fa ; int sub; }set ; #define exp 1e-10//精度 struct Node { double x ,y; }; struct line { Node A,B; }l ; int judge(Node A,Node B,Node C, Node D) { double f1 = (A.y-C.y)*(A.x-B.x)-(A.x-C.x)*(A.y-B.y);//AC X AB double f2 = (A.y-D.y)*(A.x-B.x)-(A.x-D.x)*(A.y-B.y);//AD X AB double f3 = (C.y-A.y)*(C.x-D.x)-(C.x-A.x)*(C.y-D.y);//CA X CD double f4 = (C.x-D.x)*(C.y-B.y)-(C.x-B.x)*(C.y-D.y);//CB X CD if(f1*f2<=exp && f3*f4<=exp) return 1; return 0 ; } int find(int x ) { int i, j , k ; i = x ; int sum = 0 ; while(set[i].fa!=i) { i = set[i].fa; } j = x ; return i ; } void join(int x ,int y ) { int fx = find(x); int fy = find(y); if(fx!=fy) { set[fx].fa=fy; set[fy].sub+=set[fx].sub; } } int main() { int t ; scanf("%d",&t); while(t--) { int n ; scanf("%d",&n); for(int i = 0 ;i<=n;i++) { set[i].fa = i ; set[i].sub=1; } int cnt = 1 ; while(n--) { char ch; scanf(" %c",&ch); if(ch=='P') { scanf("%lf%lf%lf%lf",&(l[cnt].A.x),&(l[cnt].A.y),&(l[cnt].B.x),&(l[cnt].B.y)); //printf("A(%0.4lf,%.4lf) B(%.4lf,%.4lf)\n",l[cnt].A.x,l[cnt].A.y,l[cnt].B.x,l[cnt].B.y);//注意double使用lf读,float使用f(float 最好不用,精度太低) for(int i = 1 ; i < cnt;i++) { if(judge(l[cnt].A,l[cnt].B,l[i].A,l[i].B)==1) { join(i,cnt); } } cnt++; } else { int q ; scanf("%d",&q); printf("%d\n",set[find(q)].sub); } } if(t) printf("\n");//注意输出格式呀 } return 0 ; }
相关文章推荐
- ios真机测试,Ineligible Devices,不可以选中真机
- 我的Java开发学习之旅------>解惑Java进行三目运算时的自动类型转换
- Split / Partition a collection into smaller collections - Java - Tutorial
- How to implement an ArrayList structure in Java - Tutorial
- Sublime Text 3 常用快捷键
- How to implement common datastructures (List, Stack, Map) in plain Java - Tutorial
- java中hashcode()和equals()的详解
- Windows Phone 七、XML序列化
- 对1...n,数组长度未知进行交换排序(无重复值,时间复杂度O(n), 空间复杂度O(1))
- css实现布局
- IOS开发 如何给ViewController添加stroyboard entry pointer?
- Java Logging: LogManager
- Java Logging: Configuration
- 2014年最新前端开发面试题(题目列表+答案 完整版)
- Java Logging: LogRecord
- Java中Comparable和Comparator实现对象比较
- GirdLayout布局:更改其中的TextView控件的TextSize属性后,出现控件未对齐情况
- Python小知识(重要)二
- 类的加载顺序
- Java Logging API - Tutorial