HDU 1558 Segment set
来源:互联网 发布:mac双系统os系统消失 编辑:程序博客网 时间:2024/06/06 11:41
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558
题目大意:询问与某条线段相交的线段有多少条,间接的也算。
算法分析,关键是求线段交点,如能判断线段是否相交,用并查集维护每个集合的个数就行了。
对于判断线段是否相交
这里并没有采用快速排斥+跨立实验,原因是采用那个不能求出线段交点。这里采用的方法是求出线段交点,然后判断交点是否都在两条线段上。
求交点注意设置精度,否则必然WA。
具体分析过程请参考《挑战程序设计竞赛》计算几何那章的内容,说得很详细,此处不再赘述。
下面是AC代码:
#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<sstream>#include<fstream>#include<vector>#include<map>#include<stack>#include<list>#include<set>#include<queue>#define LL long long#define lson l,m,rt<<1#define rson m+1,r,rt<<1 | 1using namespace std;const int maxn=1005,inf=1<<29;int dir[][2]={ {0,1},{-1,0},{0,-1},{1,0},{-1,1},{-1,-1},{1,-1},{1,1}};int n,m,t,fa[maxn],num[maxn];double EPS=1e-10;double add(double a,double b){ if(abs(a+b)<EPS*(abs(a)+abs(b))) return 0; return a+b;}struct P{ double x,y; P(){} //P(double x,double y):x(x),y(y){} P(double _x,double _y) { x=_x; y=_y; } P operator +(P p) { return P(add(x,p.x),add(y,p.y)); } P operator -(P p) { return P(add(x,-p.x),add(y,-p.y)); } P operator *(double d) { return P(x*d,y*d); } double dot(P p)//内积 { return add(x*p.x,y*p.y); } double det(P p)//外积 { return add(x*p.y,-p.x*y); }};struct v{ P p,q;}a[maxn];bool on_seg(P p1,P p2,P q)//判断点q是否在线段p1p2上{ return (p1-q).det(p2-q)==0&&(p1-q).dot(p2-q)<=0;}P intersection(P p1,P p2,P q1,P q2)//计算两线段的交点{ return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));}bool judge(v s1,v s2)//判断两条线段是否相交{ if((s1.p-s1.q).det(s2.p-s2.q)==0)//如果线段平行 { return on_seg(s1.p,s1.q,s2.p)|| on_seg(s1.p,s1.q,s2.q)|| on_seg(s2.p,s2.q,s1.p)|| on_seg(s2.p,s2.q,s1.q); } else//不平行 { P r=intersection(s1.p,s1.q,s2.p,s2.q); //cout<<"x = "<<r.x<<" y= "<<r.y<<endl; return on_seg(s1.p,s1.q,r)&&on_seg(s2.p,s2.q,r); }}int Find(int x){ if(fa[x]==x) return x; return fa[x]=Find(fa[x]);}void Merge(int x,int y){ x=Find(x),y=Find(y); if(x!=y) { fa[y]=x; num[x]+=num[y]; }}int main(){ cin>>t; v s1,s2; while(t--) { cin>>n; int cnt=1; for(int i=0;i<maxn;i++) fa[i]=i,num[i]=1; while(n--) { char op; cin>>op; if(op=='P') { cin>>a[cnt].p.x>>a[cnt].p.y>>a[cnt].q.x>>a[cnt].q.y; for(int i=1;i<cnt;i++) if(judge(a[i],a[cnt])) Merge(i,cnt); cnt++; } else { int y; cin>>y; y=Find(y); cout<<num[y]<<endl; } } if(t) cout<<endl; } return 0;}
0 0
- HDU 1558 Segment Set
- hdu 1558 Segment set
- hdu 1558 Segment set
- hdu 1558 Segment set
- HDU 1558 Segment set
- HDU 1558 Segment set
- hdu 1558 Segment set
- HDU-1558-Segment set
- hdu 1558:Segment set
- HDU 1558 Segment set
- HDU 1558 Segment set
- HDU-1558-Segment set
- hdu 1558 Segment set 5.1.4
- hdu 1558 Segment set (并查集)
- HDU 1558 Segment set 并查集
- 并查集 HDU 1558 Segment set
- HDU Segment set
- HDU 1558 Segment set, 计算几何+并查集
- 谈web开发
- 说文解字----矩阵分析(二)特征值特征向量 奇异值分解(SVD)
- iOS-UITableviewCell的重用机制
- stm32串口接收、TF卡存储丢数现象解析与总结
- 关于Spring的69个面试问答——终极列表
- HDU 1558 Segment set
- 说说Python程序的执行过程
- java marker interface
- Oracle 中查看用户建立的所有触发器
- android中NavigationDrawer的使用以及添加drawer切换时的动画效果
- 所谓的归并排序
- ActiveMQ持久化方式
- 假设一个集合有N篇文章
- 浅谈2—SAT问题