HDU1558 - Segment set: http://acm.hdu.edu.cn/showproblem.php?pid=1558
题目大意: 输入一些线段的端点坐标,若两线段相交,则把他们合并成一个集合,输入数据里会有k,问和k线段相交的线段的数目(包括自己)
思路: 每次输入一条线段,都从头扫描一次. 找出之前输入的线段里面,所有和其相交的线段,并且合并(合并用的是线段的ID). 就是: 并查集 + 判断线段相交
代码:
#include <iostream> #include <cstring> #define maxn 1005 using namespace std; int father[maxn]; struct point{ double x1,y1,x2,y2; }p[maxn];//结构体储存线段的两个端点坐标 bool judge(point x,point y)//利用 叉积 判断线段相交 { double m=(y.x2-y.x1)*(x.y1-y.y1)-(y.y2-y.y1)*(x.x1-y.x1); double n=(y.x2-y.x1)*(x.y2-y.y1)-(y.y2-y.y1)*(x.x2-y.x1); if(m*n<=0)return true; return false; } int find(int x) { return x == father[x] ? x : father[x] = find(father[x]); } void join(int x,int y) { x=find(x),y=find(y); if(x!=y) father[x]=y; } int main() { int t,n,k; int count,flag; char s; cin>>t; while(t--) { for(int i=0;i<maxn;i++)father[i]=i; cin>>n; flag=1;//记录的是线段的数目 for(int i=0;i<n;i++) { cin>>s; if(s=='P') { cin>>p[flag].x1>>p[flag].y1>>p[flag].x2>>p[flag].y2; for(int j=1;j<flag;j++)//每次输入都从头开始扫描之前输入了的线段,判断当前线段是否会和他们相交 { if(judge(p[flag],p[j])&&judge(p[j],p[flag]))//判断两线段是否相交 join(flag,j);//相交则将他们合并 } flag++; }else{ count=0; cin>>k; int x=find(k); for(int j=0;j<flag;j++)//计算与k线段是同一集合的线段数目 if(find(j)==x)count++; cout<<count<<endl; } } if(t)cout<<endl; } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU1558 - Segment set 并查集 + 判断线段相交
原文地址:http://blog.csdn.net/p_rogrammer/article/details/48009819