简单的计算几何题,判断两线段是否相交。将相交的两线段使用并查集归到一类中。查询时输出线段对应集合中元素的个数。
#include<stdio.h> struct Point{ double x,y; }; struct Segment{ Point s,e; }node[1010]; int n,parent[1010]; int getAbs(int value) { if(value>=0)return value; return -value; } int getParent(int a){ while(parent[a]>0)a=parent[a]; return a; } void Union(int a,int b) { int r1 = getParent(a); int r2 = getParent(b); if(r1!=r2) { if(r1<r2) { parent[r1]+=parent[r2];//合并两个集合时,计算两个集合的元素个数 parent[r2]=r1; }else{ parent[r2]+=parent[r1]; parent[r1]=r2; } } } double max(double a,double b) { if(a>=b)return a; return b; } double min(double a,double b) { if(a>=b)return b; return a; } /** * 计算向量 ps,pe的叉积 */ double multiply(Point p,Point s,Point e) { return (s.x-p.x)*(e.y-p.y)-(e.x-p.x)*(s.y-p.y); } int main() { int t,n,i,j,num,cnt; char command; scanf("%d",&t); while(t--) { scanf("%d",&n); cnt=0; //初始时每个元素都是一个集合 for(i=1;i<=n;i++)parent[i]=-1; for(i=1;i<=n;i++) { getchar(); scanf("%c",&command); if(command=='P'){ cnt++; scanf("%lf%lf%lf%lf",&node[cnt].s.x,&node[cnt].s.y,&node[cnt].e.x,&node[cnt].e.y); for(j=1;j<cnt;j++) { //判断第cnt个线段是否与前面的cnt-1个线段有相交。 if(max(node[cnt].s.x,node[cnt].e.x)>=min(node[j].s.x,node[j].e.x) && max(node[j].s.x,node[j].e.x)>=min(node[cnt].s.x,node[cnt].e.x) && max(node[cnt].s.y,node[cnt].e.y)>=min(node[j].s.y,node[j].e.y) && max(node[j].s.y,node[j].e.y)>=min(node[cnt].s.y,node[cnt].e.y) && multiply(node[cnt].s,node[j].s,node[j].e)*multiply(node[cnt].e,node[j].s,node[j].e)<=0 && multiply(node[j].s,node[cnt].s,node[cnt].e)*multiply(node[j].e,node[cnt].s,node[cnt].e)<=0) { //有相交就合并集合 Union(cnt,j); } } }else { scanf("%d",&num); //当parent为负数时,其绝对值就是该集合的元素个数。 printf("%d ",getAbs(parent[getParent(num)])); } } if(t!=0) { printf(" "); } } return 0; }